home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fscheck / RCS / fscheck.c,v < prev    next >
Encoding:
Text File  |  1992-06-10  |  149.7 KB  |  6,320 lines

  1. head     1.38;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.38
  10. date     92.06.09.21.48.59;  author jhh;  state Exp;
  11. branches ;
  12. next     1.37;
  13.  
  14. 1.37
  15. date     90.11.01.23.27.34;  author jhh;  state Exp;
  16. branches ;
  17. next     1.36;
  18.  
  19. 1.36
  20. date     90.10.10.15.28.44;  author mendel;  state Exp;
  21. branches ;
  22. next     1.35;
  23.  
  24. 1.35
  25. date     90.10.10.11.21.46;  author jhh;  state Exp;
  26. branches ;
  27. next     1.34;
  28.  
  29. 1.34
  30. date     90.05.01.15.36.36;  author jhh;  state Exp;
  31. branches ;
  32. next     1.33;
  33.  
  34. 1.33
  35. date     90.02.14.15.55.20;  author jhh;  state Exp;
  36. branches ;
  37. next     1.32;
  38.  
  39. 1.32
  40. date     89.10.03.17.47.12;  author jhh;  state Exp;
  41. branches ;
  42. next     1.31;
  43.  
  44. 1.31
  45. date     89.10.03.11.08.59;  author jhh;  state Exp;
  46. branches ;
  47. next     1.30;
  48.  
  49. 1.30
  50. date     89.09.25.16.41.03;  author jhh;  state Exp;
  51. branches ;
  52. next     1.29;
  53.  
  54. 1.29
  55. date     89.08.25.22.24.25;  author jhh;  state Exp;
  56. branches ;
  57. next     1.28;
  58.  
  59. 1.28
  60. date     89.07.31.17.43.27;  author jhh;  state Exp;
  61. branches ;
  62. next     1.27;
  63.  
  64. 1.27
  65. date     89.06.21.23.55.49;  author jhh;  state Exp;
  66. branches ;
  67. next     1.26;
  68.  
  69. 1.26
  70. date     89.02.28.12.21.48;  author jhh;  state Exp;
  71. branches ;
  72. next     1.25;
  73.  
  74. 1.25
  75. date     88.12.04.21.33.57;  author nelson;  state Exp;
  76. branches ;
  77. next     1.24;
  78.  
  79. 1.24
  80. date     88.09.20.15.13.32;  author nelson;  state Exp;
  81. branches ;
  82. next     1.23;
  83.  
  84. 1.23
  85. date     88.09.20.13.38.04;  author douglis;  state Exp;
  86. branches ;
  87. next     1.22;
  88.  
  89. 1.22
  90. date     88.07.19.11.45.46;  author douglis;  state Exp;
  91. branches ;
  92. next     1.21;
  93.  
  94. 1.21
  95. date     88.06.06.12.02.40;  author brent;  state Exp;
  96. branches 1.21.1.1;
  97. next     1.20;
  98.  
  99. 1.20
  100. date     88.06.02.12.58.50;  author brent;  state Exp;
  101. branches ;
  102. next     1.19;
  103.  
  104. 1.19
  105. date     87.10.21.11.03.01;  author nelson;  state Exp;
  106. branches ;
  107. next     1.18;
  108.  
  109. 1.18
  110. date     87.10.21.10.37.47;  author nelson;  state Exp;
  111. branches ;
  112. next     1.17;
  113.  
  114. 1.17
  115. date     87.10.15.15.16.16;  author nelson;  state Exp;
  116. branches ;
  117. next     1.16;
  118.  
  119. 1.16
  120. date     87.10.12.17.49.03;  author nelson;  state Exp;
  121. branches ;
  122. next     1.15;
  123.  
  124. 1.15
  125. date     87.09.30.10.48.45;  author nelson;  state Exp;
  126. branches ;
  127. next     1.14;
  128.  
  129. 1.14
  130. date     87.08.10.10.48.03;  author nelson;  state Exp;
  131. branches ;
  132. next     1.13;
  133.  
  134. 1.13
  135. date     87.07.14.14.37.17;  author nelson;  state Exp;
  136. branches ;
  137. next     1.12;
  138.  
  139. 1.12
  140. date     87.07.14.11.32.12;  author brent;  state Exp;
  141. branches ;
  142. next     1.11;
  143.  
  144. 1.11
  145. date     87.06.03.19.30.40;  author nelson;  state Exp;
  146. branches ;
  147. next     1.10;
  148.  
  149. 1.10
  150. date     87.06.01.15.41.47;  author nelson;  state Exp;
  151. branches ;
  152. next     1.9;
  153.  
  154. 1.9
  155. date     87.05.30.12.17.27;  author nelson;  state Exp;
  156. branches ;
  157. next     1.8;
  158.  
  159. 1.8
  160. date     87.05.27.10.13.36;  author nelson;  state Exp;
  161. branches ;
  162. next     1.7;
  163.  
  164. 1.7
  165. date     87.05.26.14.09.55;  author nelson;  state Exp;
  166. branches ;
  167. next     1.6;
  168.  
  169. 1.6
  170. date     87.04.25.10.24.20;  author brent;  state Exp;
  171. branches ;
  172. next     1.5;
  173.  
  174. 1.5
  175. date     87.04.24.17.36.45;  author douglis;  state Exp;
  176. branches ;
  177. next     1.4;
  178.  
  179. 1.4
  180. date     86.12.16.13.21.42;  author nelson;  state Exp;
  181. branches ;
  182. next     1.3;
  183.  
  184. 1.3
  185. date     86.11.10.11.33.00;  author nelson;  state Exp;
  186. branches ;
  187. next     1.2;
  188.  
  189. 1.2
  190. date     86.09.19.18.18.00;  author nelson;  state Exp;
  191. branches ;
  192. next     1.1;
  193.  
  194. 1.1
  195. date     86.07.27.12.52.54;  author nelson;  state Exp;
  196. branches ;
  197. next     ;
  198.  
  199. 1.21.1.1
  200. date     88.07.15.18.20.12;  author douglis;  state Exp;
  201. branches ;
  202. next     ;
  203.  
  204.  
  205. desc
  206. @@
  207.  
  208.  
  209. 1.38
  210. log
  211. @got rid of dependency on first partition of disk
  212. @
  213. text
  214. @/* 
  215.  * fscheck.c --
  216.  *
  217.  *    Perform consistency checks on a filesystem.
  218.   *
  219.  * Copyright 1989 Regents of the University of California
  220.  * Permission to use, copy, modify, and distribute this
  221.  * software and its documentation for any purpose and without
  222.  * fee is hereby granted, provided that the above copyright
  223.  * notice appear in all copies.  The University of California
  224.  * makes no representations about the suitability of this
  225.  * software for any purpose.  It is provided "as is" without
  226.  * express or implied warranty.
  227.  */
  228.  
  229. #ifndef lint
  230. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fscheck.c,v 1.37 90/11/01 23:27:34 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  231. #endif not lint
  232.  
  233. #include "option.h"
  234. #include "list.h"
  235. #include "fscheck.h"
  236. #include <string.h>
  237. #include <host.h>
  238. #include <sys/file.h>
  239. #include <sys/stat.h>
  240. #include <stdio.h>
  241.  
  242. int    numBlocks = 0;
  243. int    numFiles = 0;
  244. int    numBadDesc = 0;
  245. int    numFrags = 0;
  246. int    errorType = EXIT_OK;
  247. int    foundError = 0;
  248. int    fdBitmapError = 0;
  249. Boolean    tooBig = FALSE;
  250. Ofs_DomainHeader  *domainPtr;
  251. int        partFID;
  252. Boolean patchHeader = FALSE;
  253. Boolean    attached    = FALSE;
  254.  
  255. /*
  256.  * The following are used to go from a command line like
  257.  * fscheck -dev rsd0 -part b
  258.  * to /dev/rsd0a     - for the partition that has the disk label
  259.  * and to /dev/rsd0b    - for the partition to format.
  260.  */
  261. char *deviceName;        /* Set to "rsd0" or "rxy1", etc. */
  262. char *partName;            /* Set to "a", "b", "c" ... "g" */
  263. char defaultFirstPartName[] = "a";
  264. char *firstPartName = defaultFirstPartName;
  265. char defaultDevDirectory[] = "/dev/";
  266. char *devDirectory = defaultDevDirectory;
  267. char *outputFileName = NULL;
  268.  
  269. int hostID = -1;
  270. int writeDisk = 0;
  271. int verbose = 0;
  272. int silent = 0;
  273. int clearDomainNumber = 0;
  274. int recoveryCheck = 0;
  275. int badBlockInit = 0;
  276. int patchRoot = 0;
  277. int rawOutput = FALSE;
  278. int maxHeapSize = -1;
  279. int bufferSize = BUFSIZ;
  280. int heapSize = 0;
  281. int noCopy = FALSE;
  282. int blocksToRead = 1;
  283. int debug = FALSE;
  284. int clearFixCount = FALSE;
  285. int bitmapVerbose = 0;
  286. int numReboot = 4;
  287. int blockToFind = -1;
  288. int fileToPrint = -1;
  289. int dontRecheck = 0;
  290. int setCheckedBit = FALSE;
  291.  
  292. Option optionArray[] = {
  293.     {OPT_STRING, "dev", (Address)&deviceName,
  294.     "Required: Name of device, eg \"rsd0\" or \"rxy1\""},
  295.     {OPT_STRING, "part", (Address)&partName,
  296.     "Required: Partition ID: (a, b, c, d, e, f, g)"},
  297.     {OPT_STRING, "dir", (Address)&devDirectory,
  298.     "Name of device directory (\"/dev/\")"},
  299.     {OPT_STRING, "initialPart", (Address)&firstPartName,
  300.     "Name of initial partition (\"a\")"},
  301.     {OPT_TRUE, "write", (Address)&writeDisk,
  302.     "Write disk "},
  303.     {OPT_TRUE, "silent", (Address)&silent,
  304.     "Don't say anything unless there's a problem "},
  305.     {OPT_TRUE, "verbose", (Address)&verbose,
  306.     "Output information about differences in bitmaps "},
  307.     {OPT_TRUE, "fixRoot", (Address)&patchRoot,
  308.      "Re-create the missing/corrupt root directory."},
  309.     {OPT_TRUE, "clear", (Address)&clearDomainNumber,
  310.     "Clear the domain number field stored in the summary sector"},
  311.     {OPT_INT, "hostID", (Address)&hostID,
  312.     "Update the host ID in the disk header"},
  313.     {OPT_TRUE, "badBlock", (Address)&badBlockInit,
  314.     "Initialize the bad block file descriptor"},
  315.     {OPT_STRING, "outputFile", (Address)&outputFileName,
  316.     "Name of file in which to store output."},    
  317.     {OPT_TRUE, "rawOutput", (Address) &rawOutput,
  318.     "Bypass the filesystem when writing the output into the file."},
  319.     {OPT_INT, "heapLimit", (Address)&maxHeapSize,
  320.     "Maximum amount of dynamic storage allowed."},
  321.     {OPT_INT, "bufferSize", (Address)&bufferSize,
  322.     "Size of buffer for output file stream."},
  323.     {OPT_TRUE, "delete", (Address)&noCopy,
  324.     "Truncate files containing duplicate blocks."},
  325.     {OPT_TRUE, "debug", (Address)&debug,
  326.     "Print debugging information."},
  327.     {OPT_INT, "readBlock", (Address)&blocksToRead,
  328.     "Number of blocks to read at a time."},
  329.     {OPT_TRUE, "clearFixCount", (Address)&clearFixCount,
  330.     "Clear the count of consecutive disk fixes in summary sector"},
  331.     {OPT_TRUE, "bitmapVerbose", (Address)&bitmapVerbose,
  332.     "Print information about bitmap errors."},
  333.     {OPT_INT, "numReboot", (Address)&numReboot,
  334.     "Number of consecutive runs before returning EXIT_NOREBOOT"},
  335.     {OPT_INT, "block", (Address)&blockToFind,
  336.     "Block to look for"},
  337.     {OPT_INT, "file", (Address)&fileToPrint,
  338.     "File to print"},
  339.     {OPT_TRUE, "cond", (Address)&dontRecheck,
  340.     "Don't check the disk if it has just been checked successfully"},
  341.     {OPT_TRUE, "setCheck", (Address)&setCheckedBit,
  342.     "If the disk is checked and fixed ok set a bit in the summary sector"},
  343. };
  344. int numOptions = sizeof(optionArray) / sizeof(Option);
  345.  
  346. /*
  347.  * Forward Declarations.
  348.  */
  349. void        CheckFilesystem();
  350. int        RecoveryCheck();
  351.  
  352. /*
  353.  * The last file that an error message was printed about.
  354.  */
  355. int        lastErrorFD = -1;
  356. int        fixCount = 0;
  357.  
  358.  
  359. /*
  360.  *----------------------------------------------------------------------
  361.  *
  362.  * main --
  363.  *
  364.  *    Create the required file names from the command line
  365.  *    arguments.  Then open the first partition on the disk
  366.  *    because it contains the disk label, and open the partition
  367.  *    that is to be checked.
  368.  *
  369.  * Results:
  370.  *
  371.  * Side effects:
  372.  *    File opening.
  373.  *
  374.  *----------------------------------------------------------------------
  375.  */
  376. main(argc, argv)
  377.     int argc;
  378.     char *argv[];
  379. {
  380.     char    firstPartitionName[64];
  381.     char    partitionName[64];
  382.     int        partition;
  383.     u_char      *streamBuffer;
  384.     int        outputFID;
  385.     char    *timeString;
  386.     struct timeval tp;
  387.     struct timezone tzp;
  388.     int        argsReturned;
  389.  
  390.  
  391.     argsReturned = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  392.     if (argsReturned > 1) {
  393.     Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  394.     exit(EXIT_BAD_ARG);
  395.     }
  396.     /*
  397.      * Set up stream for output to file, as well as output to stderr.
  398.      */
  399.     if (outputFileName == NULL) {
  400.     outputFile = NULL;
  401.     } else if (!rawOutput) {
  402.     outputFile = fopen(outputFileName,"a+");
  403.     if (outputFile == NULL ) {
  404.         OutputPerror("fscheck: Can't open output file \"%s\\n", 
  405.         outputFileName);
  406.         exit(EXIT_HARD_ERROR);
  407.     }
  408.     if (bufferSize != BUFSIZ) {
  409.         if (setvbuf(outputFile,(char *) NULL,_IOFBF,bufferSize)) {
  410.         Output(stderr,
  411.                "fscheck: Unable to change output buffer size.\n");
  412.         if (maxHeapSize > 0) {
  413.             maxHeapSize -= bufferSize;
  414.         }
  415.         }
  416.     }
  417.     } else {
  418.     if (bufferSize > FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE) {
  419.         Output(stderr,
  420. "Maximum buffer size allowed when using raw output is %d bytes.\n",
  421.         FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE);
  422.         exit(EXIT_BAD_ARG);
  423.     }
  424.     Alloc(streamBuffer,u_char,bufferSize);
  425.         Stdio_Setup(outputFile,0,1,streamBuffer,bufferSize,NULL,
  426.         WriteOutputFile, CloseOutputFile,NULL);
  427.     }
  428.     if (rawOutput) {
  429.     Output(stderr,"      \n");
  430.     }
  431.     gettimeofday(&tp,&tzp);
  432.     timeString = asctime(localtime(&tp.tv_sec));
  433.     if (verbose) {
  434.     Output(stderr,"***** Fscheck *****\n");
  435.     }
  436.     if (!silent) {
  437.     Output(stderr,"%s",timeString);
  438.     }
  439.     if (tooBig) {
  440.     Output(stderr,"fscheck: Heap limit too small.\n");
  441.     exit(EXIT_MORE_MEMORY);
  442.     }
  443.     if (deviceName == (char *)0) {
  444.     Output(stderr, "Specify device name with -dev option\n");
  445.     exit(EXIT_BAD_ARG);
  446.     }
  447.     if (partName == (char *)0) {
  448.     Output(stderr, "Specify partition with -part option\n");
  449.     exit(EXIT_BAD_ARG);
  450.     }
  451.     if (blocksToRead <= 0) {
  452.     Output(stderr,"blocksToRead value %d illegal - using 1.\n");
  453.     blocksToRead = 1;
  454.     }
  455.     if (patchRoot && !writeDisk) {
  456.     Output(stderr, 
  457.          "Sorry but you can't patch the root without writing the disk.\n");
  458.         exit(EXIT_BAD_ARG);
  459.     }
  460.     if (hostID != -1) {
  461.     patchHeader = TRUE;
  462.     }
  463.     /*
  464.      * Gen up the name of the first partition on the disk,
  465.      * and the name of the partition that needs to be checked.
  466.      */
  467.     (void)strcpy(firstPartitionName, devDirectory);  /* eg. /dev/ */
  468.     (void)strcpy(partitionName, devDirectory);    
  469.     (void)strcat(firstPartitionName, deviceName);      /* eg. /dev/rxy0 */
  470.     (void)strcat(partitionName, deviceName);    
  471.     (void)strcat(firstPartitionName, firstPartName);  /* eg. /dev/rxy0a */
  472.     (void)strcat(partitionName, partName);          /* eg. /dev/rxy0b */
  473.  
  474.     partFID = open(partitionName, writeDisk ? O_RDWR : O_RDONLY);
  475.     if (partFID < 0) {
  476.     OutputPerror("fscheck: Can't open partition to check ");
  477.     exit(EXIT_HARD_ERROR);
  478.     }
  479.  
  480.     partition = partName[0] - 'a';
  481.     if (partition < 0 || partition > 7) {
  482.     Output(stderr,
  483.          "fscheck: Can't determine partition index from the partition name\n");
  484.     exit(EXIT_BAD_ARG);
  485.     }
  486.     if ((maxHeapSize > 0) && (bufferSize >= maxHeapSize)) {
  487.     Output(stderr,
  488.            "fscheck: Size of output buffer exceeds maximum heap size.\n");
  489.     exit(EXIT_MORE_MEMORY);
  490.     }
  491.     CheckFilesystem(partFID, partition);
  492.  
  493.     if (outputFile != NULL) {
  494.     (void)fclose(outputFile);
  495.     }
  496.     (void)close(partFID);
  497.     if (foundError) {
  498.     if (attached) {
  499.         exit(EXIT_REBOOT);
  500.     }
  501.     if (errorType != EXIT_OK) {
  502.         exit(errorType);
  503.     }
  504.     exit(EXIT_SOFT_ERROR);
  505.     }
  506.     exit(EXIT_OK);
  507. }
  508.  
  509. unsigned char *fdBitmapPtr;
  510. unsigned char *cylBitmapPtr;
  511.  
  512. /*
  513.  * Array to provide the ability to set and extract bits out of a bitmap byte.
  514.  */
  515. unsigned char bitmasks[BITS_PER_BYTE] = {
  516.     0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1
  517. };
  518.  
  519. void         ReadDomainHeader();
  520. void        CheckDirTree();
  521. void        CheckBlocks();
  522. unsigned char     *ReadFileDescBitmap();
  523. unsigned char     *ReadBitmap();
  524. FdInfo        *ReadFileDesc();
  525. void        WriteDomainHeader();
  526. void        WriteFileDescBitmap();
  527. void        WriteBitmap();
  528. void        WriteFileDesc();
  529. void        WriteSummaryInfo();
  530. void        CheckFDBitmap();
  531. void        SetBadDescBitmap();
  532. void        RelocateFD();
  533.  
  534. int    num1KBlocks;
  535. int    bytesPerCylinder;
  536.  
  537. List_Links    copyListHdr;
  538. List_Links    relocListHdr;
  539. List_Links    modListHdr;
  540. #define tempCopyList &tempCopyListHdr;
  541.  
  542.  
  543. /*
  544.  *----------------------------------------------------------------------
  545.  *
  546.  * CheckFilesystem --
  547.  *
  548.  *    Perform consistency checks on the file system.
  549.  *
  550.  * Results:
  551.  *    An error code, probably from a read.
  552.  *
  553.  * Side effects:
  554.  *    Error flags may be set
  555.  *
  556.  *----------------------------------------------------------------------
  557.  */
  558. void
  559. CheckFilesystem(partFID, partition)
  560.     int partFID;    /* Handle on the partition of the disk to format */
  561.     int partition;    /* Index of parition that is to be dumped */
  562. {
  563.     Disk_Label            *labelPtr;
  564.     FdInfo                *descInfoPtr;
  565.     register    FdInfo          *tDescInfoPtr;
  566.     unsigned char        *tFdBitmapPtr;
  567.     unsigned    char          *newCylBitmapPtr;
  568.     int                i, j, k;
  569.     int                fdNum;
  570.     char            *block;
  571.     Fsdm_FileDescriptor        *fdPtr;
  572.     int                sector;
  573.     unsigned int        validMask;
  574.     int                valid;
  575.     int                salvage;
  576.     unsigned char         *oldPtr;
  577.     unsigned char         *newPtr;
  578.     int                blockNum;
  579.     int                bitmapError = 0;
  580.     RelocListElement        *relocElemPtr;
  581.     CopyListElement        *copyElemPtr;
  582.     Boolean            blockModified;
  583.     Fsdm_FileDescriptor        *fdCopyPtr = NULL;
  584.     Boolean            copyUsed;
  585.     Boolean            batchRead;
  586.     char            *blockBuffer;
  587.     Boolean            blockBufferModified;
  588.     int                numFileDescBlocks;
  589.     Boolean            fdMagicOkay;
  590.     int             status;
  591.  
  592.  
  593.  
  594.     /*
  595.      * Read the copy of the super block at the beginning of the partition
  596.      * to find out basic disk geometry and where to find the domain header.
  597.      */
  598.     labelPtr = Disk_ReadLabel(partFID);
  599.     if (labelPtr == NULL) {
  600.     Output(stderr, "CheckFilesystem: Could not read disk label\n");
  601.     exit(EXIT_READ_FAILURE);
  602.     }
  603.     fflush(stderr);
  604.     fflush(stdout);
  605.     Alloc(blockBuffer, char, blocksToRead * FS_BLOCK_SIZE);
  606.     if (tooBig) {
  607.     Output(stderr,"CheckFileSystem: Heap limit too small.\n");
  608.     exit(EXIT_MORE_MEMORY);
  609.     }
  610.     domainPtr = Disk_ReadDomainHeader(partFID, labelPtr);
  611.     if (domainPtr == NULL) {
  612.     Output(stderr, "CheckFilesystem: Could not read domain header\n");
  613.     exit(EXIT_READ_FAILURE);
  614.     }
  615.     /*
  616.      * See if we need to patch the host ID in the domain header.
  617.      */
  618.     if (patchHeader) {
  619.     int        spriteID;
  620.     struct stat    attrs;
  621.  
  622.     if (hostID != 0) {
  623.         spriteID = hostID;
  624.     } else {
  625.         /*
  626.          * Determine where the disk is located so we can set the
  627.          * spriteID in the header correctly.  If the disk device is generic
  628.          * we use our own hostID, otherwise use the hostID specified
  629.          * by the device file.
  630.          */
  631.         fstat(partFID, &attrs);
  632.         if (attrs.st_devServerID == FS_LOCALHOST_ID) {
  633.         Proc_GetHostIDs((int *) NULL, &spriteID);
  634.         } else {
  635.         spriteID = attrs.st_devServerID;
  636.         }
  637.     }
  638.     if (spriteID != domainPtr->device.serverID) {
  639.         if (!silent) {
  640.         Output(stderr, "Setting hostID in disk header to 0x%x\n",
  641.                 spriteID);
  642.         }
  643.         domainPtr->device.serverID = spriteID;
  644.     } else {
  645.         if (!silent) {
  646.         Output(stderr, "Leaving hostID as 0x%x\n",spriteID);
  647.         }
  648.         patchHeader = FALSE;
  649.     }
  650.     } else if (debug) {
  651.     Output(stderr,"HostID read off disk is 0x%x\n",
  652.            domainPtr->device.serverID);
  653.     }
  654.     /*
  655.      * Read in the file descriptor bit map and the cylinder bit map.
  656.      */
  657.     fdBitmapPtr = ReadFileDescBitmap(partFID, domainPtr);
  658.     cylBitmapPtr = ReadBitmap(partFID, domainPtr);
  659.     AllocByte(newCylBitmapPtr,unsigned char,domainPtr->bitmapBlocks * 
  660.     FS_BLOCK_SIZE);
  661.     if (tooBig) {
  662.     Output(stderr,"CheckFileSystem: Heap limit too small.\n");
  663.     exit(EXIT_MORE_MEMORY);
  664.     }
  665.     bzero((Address)newCylBitmapPtr, domainPtr->bitmapBlocks * FS_BLOCK_SIZE); 
  666.     /*
  667.      * Allocate the descriptor info array.
  668.      */
  669.     Alloc(descInfoPtr,FdInfo,domainPtr->numFileDesc);
  670.     if (tooBig) {
  671.     Output(stderr,"CheckFileSystem: Heap limit too small.\n");
  672.     exit(EXIT_MORE_MEMORY);
  673.     }
  674.     bzero((Address)descInfoPtr, domainPtr->numFileDesc * sizeof(FdInfo));
  675.  
  676.     num1KBlocks = domainPtr->dataCylinders * 
  677.           domainPtr->geometry.blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK;
  678.     bytesPerCylinder = (domainPtr->geometry.blocksPerCylinder + 1) / 2;
  679.     List_Init(modList);
  680.     List_Init(relocList);
  681.     List_Init(copyList);
  682.  
  683.     /*
  684.      * Check the disk to see if the disk has been checked already.
  685.      */
  686.     if (verbose) {
  687.         Output(stderr, "Performing recovery check\n");
  688.     }
  689.     status = RecoveryCheck(partFID, labelPtr);
  690.     if (dontRecheck && status) {
  691.     if (!silent) {
  692.         Output(stderr, 
  693.     "Disk is marked as just checked. I won't bother checking it again.\n");
  694.     }
  695.     FindOutputFile();
  696.     return;
  697.     }
  698.     /*
  699.      * Recreate the file descriptor bit map and check the block counts and 
  700.      * make sure that all blocks are referenced.  Also recreate the data block
  701.      * bitmap.
  702.      */
  703.     if (verbose) {
  704.     Output(stderr, "Checking file descriptors:\n");
  705.     }
  706.  
  707.     tDescInfoPtr = descInfoPtr;
  708.     tFdBitmapPtr = fdBitmapPtr;
  709.     fdNum = 0;
  710.     numFileDescBlocks = (domainPtr->numFileDesc + FSDM_FILE_DESC_PER_BLOCK - 1) / 
  711.         FSDM_FILE_DESC_PER_BLOCK;
  712.     if (blocksToRead > numFileDescBlocks) {
  713.     blocksToRead = numFileDescBlocks;
  714.     }
  715.     for (i = 0; 
  716.      (i < numFileDescBlocks) && !tooBig;
  717.     i += blocksToRead) {
  718.     batchRead = TRUE;
  719.     if (Disk_BlockRead(partFID, domainPtr, 
  720.                domainPtr->fileDescOffset + i,
  721.                blocksToRead, (Address) blockBuffer) < 0) {
  722.         batchRead = FALSE;
  723.         OutputPerror("CheckFilesystem: read of fd's failed");
  724.     }
  725.     block = blockBuffer;
  726.     blockBufferModified = FALSE;
  727.     for (k = 0; k < blocksToRead; k++) {
  728.         if (batchRead) {
  729.         block = &(blockBuffer[k * FS_BLOCK_SIZE]);
  730.         salvage = 0;
  731.         } else {
  732.         /*
  733.          * We couldn't read all of the disk blocks at once, so try
  734.          * to read them one at a time.
  735.          */
  736.         if (Disk_BlockRead(partFID, domainPtr, 
  737.                    domainPtr->fileDescOffset + i + k,
  738.                    1, (Address) block) < 0) {
  739.             /*
  740.              * Hit a disk error reading the block.  Read it a sector
  741.              * at a time and try to salvage what we can.
  742.              */
  743.             OutputPerror("CheckFilesystem: BlockRead: Read failed");
  744.             validMask = Disk_BadBlockRead(partFID, domainPtr,
  745.                           domainPtr->fileDescOffset + i + k,
  746.                           (Address) block);
  747.             SetBadDescBitmap(domainPtr, fdNum, &tFdBitmapPtr);
  748.             salvage = 1;
  749.         }
  750.         }
  751.         if (!salvage) {
  752.         CheckFDBitmap(domainPtr, fdNum, block, &tFdBitmapPtr);
  753.         valid = 1;
  754.         }
  755.         blockModified = FALSE;
  756.         for (sector = 0; 
  757.              sector < DISK_SECTORS_PER_BLOCK && !tooBig; 
  758.          sector++) {
  759.         if (salvage) {
  760.             valid = (validMask & (1 << sector)) != 0;
  761.             numBadDesc++;
  762.         }
  763.         for (j = 0; 
  764.              j < FILE_DESC_PER_SECTOR && 
  765.              fdNum < domainPtr->numFileDesc && !tooBig;
  766.              j++, fdNum++, tDescInfoPtr++, fdPtr++) {
  767.     
  768.             int    modified = 0;
  769.             fdPtr = (Fsdm_FileDescriptor *)    
  770.                 &block[(j + (FILE_DESC_PER_SECTOR * sector)) *
  771.                 FSDM_MAX_FILE_DESC_SIZE];
  772.              if (fdPtr->magic != FSDM_FD_MAGIC) {
  773.              if (!silent) {
  774.                  Output(stderr, 
  775.      "File %d has an invalid magic number <0x%x> and is being reset.\n",
  776.                     fdNum, fdPtr->magic);
  777.                  Output(stderr,
  778.                  "Current block is %d.\n", 
  779.                  i + k + domainPtr->fileDescOffset);
  780.              }
  781.              UnmarkFDBitmap(fdNum,fdBitmapPtr);
  782.              fdMagicOkay = FALSE;
  783.              } else {
  784.              fdMagicOkay = TRUE;
  785.              }
  786.             /* 
  787.              * Make a copy of the fd to be used by elements in 
  788.              * the lists. We have to do this because we can't keep
  789.              * all of the fd's in memory at once.
  790.              */
  791.             if (fdCopyPtr == NULL) { 
  792.             Alloc(fdCopyPtr,Fsdm_FileDescriptor,1);
  793.             if (tooBig) {
  794.                 continue;
  795.             }
  796.             }
  797.             bcopy((Address)fdPtr, (Address)fdCopyPtr, 
  798.               sizeof(Fsdm_FileDescriptor));
  799.             copyUsed = FALSE;
  800.             relocElemPtr = NULL;
  801.             copyElemPtr = NULL;
  802.             if (salvage) {
  803.             if (valid && fdMagicOkay && 
  804.                 (fdPtr->flags & FSDM_FD_ALLOC)) {
  805.                 /* 
  806.                  * If the descriptor is valid and is in a disk block
  807.                  * that is bad, put the fd on a list for relocation.
  808.                  */
  809.                 Alloc(relocElemPtr,RelocListElement,1);
  810.                 if (tooBig) {
  811.                 continue;
  812.                 }
  813.                 tDescInfoPtr->flags |= FD_RELOCATE;
  814.                 relocElemPtr->origFdNum = fdNum;
  815.                 relocElemPtr->newFdNum = -1;
  816.                 relocElemPtr->fdPtr = fdCopyPtr;
  817.                 copyUsed = TRUE;
  818.             }
  819.             if (!valid) {
  820.                 tDescInfoPtr->flags |= FD_UNREADABLE;
  821.             }
  822.             }
  823.             if (valid && fdMagicOkay) {
  824.             if (fdPtr->fileType == FS_DIRECTORY) {
  825.                 tDescInfoPtr->flags |= IS_A_DIRECTORY;
  826.             }
  827.             if (fdPtr->flags & FSDM_FD_ALLOC) {
  828.                 tDescInfoPtr->flags |= FD_ALLOCATED;
  829.                 tDescInfoPtr->origLinkCount = fdPtr->numLinks;
  830.  
  831.                 CheckBlocks(partFID, domainPtr, fdNum, fdCopyPtr,
  832.                     newCylBitmapPtr, &modified,©Used);
  833.                 if (modified) {
  834.                 blockModified = TRUE;
  835.                 }
  836.                 if (tooBig) {
  837.                 continue;
  838.                 }
  839.             } else if (debug && 
  840.                        fdNum == FSDM_BAD_BLOCK_FILE_NUMBER &&
  841.                    fdPtr->firstByte == -1){
  842.                 Output(stderr,"bad block has been reset.\n");
  843.             }
  844.             }
  845.             if ((badBlockInit && fdNum == FSDM_BAD_BLOCK_FILE_NUMBER) ||
  846.                 (salvage && !valid) || !(fdMagicOkay)) {
  847.             if (badBlockInit && 
  848.                 fdNum == FSDM_BAD_BLOCK_FILE_NUMBER) {
  849.                 Output(stderr,  
  850.                    "Clearing bad block file descriptor.\n");
  851.             }
  852.             ClearFd(fdMagicOkay ? FSDM_FD_ALLOC : FSDM_FD_FREE, 
  853.                 fdCopyPtr);
  854.             blockModified = TRUE;
  855.             modified = 1;
  856.             }
  857.             if (relocElemPtr != NULL) {
  858.                List_Insert((List_Links *)relocElemPtr,
  859.                    LIST_ATREAR(relocList));
  860.             }
  861.             if (modified) {
  862.             bcopy((Address)fdCopyPtr, (Address)fdPtr, 
  863.                   sizeof(Fsdm_FileDescriptor));
  864.                 fdPtr->version++;
  865.             }
  866.             if (copyUsed) {
  867.             fdCopyPtr = NULL;
  868.             }
  869.         }
  870.         }
  871.         if (blockModified) {
  872.         blockBufferModified = TRUE;
  873.         if (!batchRead && writeDisk) {
  874.             if (Disk_BlockWrite(partFID, domainPtr,
  875.                     domainPtr->fileDescOffset + i + k,
  876.                     1, (Address) block) < 0) {
  877.             OutputPerror("CheckFileSystem: FD write failed");
  878.             exit(EXIT_WRITE_FAILURE);
  879.             }
  880.         }
  881.         }
  882.     }
  883.     if (batchRead && blockBufferModified && writeDisk) {
  884.         if (Disk_BlockWrite(partFID, domainPtr,
  885.                 domainPtr->fileDescOffset + i,
  886.                 blocksToRead, (Address) blockBuffer) < 0) {
  887.         OutputPerror("CheckFileSystem: FD write failed");
  888.         exit(EXIT_WRITE_FAILURE);
  889.         }
  890.     }
  891.     }
  892.     if (!silent && fdBitmapError) {
  893.     Output(stderr, "Found error in file descriptor bitmap\n");
  894.     }
  895.  
  896.  
  897.     /*
  898.      * We now know which descriptors, if any, need to be relocated.  Allocate
  899.      * new descriptors to hold the information.
  900.      */
  901.  
  902.     if (!(List_IsEmpty(relocList))) {
  903.     LIST_FORALL(relocList, (List_Links *)relocElemPtr) {
  904.         RelocateFD(domainPtr, descInfoPtr, relocElemPtr);
  905.     }
  906.     }
  907.     /*
  908.      * Fix all blocks that appeared in more than one file.
  909.      */
  910.     if (!(List_IsEmpty(copyList))) {
  911.     int status = 0;
  912.  
  913.     if (verbose) {
  914.         Output(stderr, "\nCopying duplicate blocks\n");
  915.     }
  916.     LIST_FORALL(copyList, (List_Links *)copyElemPtr) {
  917.         List_Remove((List_Links *) copyElemPtr);
  918.         if (status != -1 && !noCopy) {
  919.         status = CopyBlock(domainPtr, descInfoPtr, partFID, 
  920.                    newCylBitmapPtr, copyElemPtr);
  921.         }
  922.         if ((copyElemPtr->parentType == FD) && 
  923.         !((descInfoPtr[copyElemPtr->parentNum].flags & 
  924.          (ON_MOD_LIST | FD_RELOCATE)))) {
  925.          free((Address) copyElemPtr->fdPtr);
  926.         }
  927.         free((Address) copyElemPtr);
  928.     }
  929.     }
  930.     /*
  931.      * Go through the file system starting at the root and perform a 
  932.      * consistency check.
  933.      */
  934.     if (!tooBig) {
  935.     if (verbose) {
  936.         Output(stderr, "Traversing directory tree:\n\n");
  937.     }
  938.     
  939.     CheckDirTree(partFID, domainPtr, descInfoPtr, fdBitmapPtr,
  940.              newCylBitmapPtr);
  941.     } else {
  942.     Output(stderr,
  943.            "NOT traversing directory tree because heap limit exceeded.\n"
  944.            );
  945.     }
  946.     /*
  947.      * Now compare the two data block bitmaps.
  948.      */
  949.     if (verbose) {
  950.     Output(stderr, "Comparing old and new data block bit maps:\n");
  951.     }
  952.     /*
  953.      * Block 0 is reserved for the root directory, so mark it as in use.
  954.      * There is code in the file system that will panic if block 0 is
  955.      * reallocated.
  956.      */
  957.     if ((*cylBitmapPtr & 0xf0) != 0xf0) {
  958.     if (!silent) {
  959.         Output(stderr, "Block 0 is free. Marking it used.\n");
  960.     }
  961.     foundError = 1;
  962.     bitmapError = 1;
  963.     }
  964.     *newCylBitmapPtr |= 0xf0;
  965.     *cylBitmapPtr |= 0xf0;
  966.     for (oldPtr = cylBitmapPtr, newPtr = newCylBitmapPtr, i = 0, blockNum = 0; 
  967.      i < domainPtr->dataCylinders; 
  968.      i++, oldPtr = &cylBitmapPtr[bytesPerCylinder * i], 
  969.           newPtr = &newCylBitmapPtr[bytesPerCylinder * i]) {
  970.     for (j = 0; 
  971.          j < bytesPerCylinder; 
  972.          j++, oldPtr++, newPtr++, blockNum += 2) {
  973.         if ((*oldPtr & 0xf0) != (*newPtr & 0xf0)) {
  974.         if (bitmapVerbose) {
  975.             Output(stderr,"Block %d: old %x new %x.\n",
  976.             blockNum * FS_FRAGMENTS_PER_BLOCK,
  977.             (*oldPtr & 0xf0) >> 4, (*newPtr & 0xf0) >> 4);
  978.         }
  979.         foundError = 1;
  980.         bitmapError = 1;
  981.         } 
  982.         if ((*oldPtr & 0x0f) != (*newPtr & 0x0f)) {
  983.         if (bitmapVerbose) {
  984.             Output(stderr,"Block %d: old %x new %x.\n",
  985.                (blockNum + 1) * FS_FRAGMENTS_PER_BLOCK,
  986.                *oldPtr & 0x0f, *newPtr & 0x0f);
  987.         }
  988.         foundError = 1;
  989.         bitmapError = 1;
  990.         }
  991.     }
  992.     }
  993.     if (!silent && bitmapError) {
  994.     Output(stderr, "Found error in data block bitmap\n");
  995.     }
  996.     fflush(stderr);
  997.  
  998.     /*
  999.      * Print status information about disk.
  1000.      */
  1001.     Output(stdout, 
  1002.         "%d files, %d blocks in use, %d blocks free, %d fragments\n",
  1003.         numFiles, numBlocks, domainPtr->dataBlocks * 4 - numBlocks,
  1004.         numFrags);
  1005.  
  1006.  
  1007.     if (foundError) {
  1008.     fixCount++;
  1009.     if (fixCount > numReboot) {
  1010.         foundError = 1;
  1011.         errorType = EXIT_NOREBOOT;
  1012.     }
  1013.     } else {
  1014.     fixCount = 0;
  1015.     }
  1016.     if (!writeDisk) {
  1017.     return;
  1018.     }
  1019.  
  1020.     if (verbose) {
  1021.     Output(stderr, "Writing disk\n");
  1022.     }
  1023.     fflush(stderr);
  1024.  
  1025.     /*
  1026.      * Write the file descriptor and data block bitmaps back out along with
  1027.      * the file descriptors.
  1028.      */
  1029.     if (patchHeader) {
  1030.     status = Disk_WriteDomainHeader(partFID, labelPtr, domainPtr);
  1031.     if (status != 0) {
  1032.         Output(stderr, "Unable to write domain header.\n");
  1033.         exit(EXIT_WRITE_FAILURE);
  1034.     }
  1035.     }
  1036.  
  1037.     WriteFileDescBitmap(partFID, domainPtr, fdBitmapPtr);
  1038.     WriteBitmap(partFID, domainPtr, newCylBitmapPtr);
  1039.  
  1040.     /*
  1041.      * Write out any modified file descriptors on the modified list.
  1042.      */
  1043.     WriteFileDesc(partFID, domainPtr, modList, descInfoPtr);
  1044.     WriteFileDesc(partFID, domainPtr, relocList, descInfoPtr);
  1045.     WriteSummaryInfo(partFID, labelPtr, domainPtr, 
  1046.                 numBlocks, numFiles);
  1047. }
  1048.  
  1049.  
  1050. /*
  1051.  *----------------------------------------------------------------------
  1052.  *
  1053.  * CheckBlocks --
  1054.  *
  1055.  *    Check all the blocks associated with a file descriptor.
  1056.  *
  1057.  *
  1058.  * Results:
  1059.  *    None.
  1060.  *
  1061.  * Side effects:
  1062.  *    Error flags may be set.
  1063.  *
  1064.  *----------------------------------------------------------------------
  1065.  */
  1066. void
  1067. CheckBlocks(partFID, domainPtr, fdNum, fdPtr, newCylBitmapPtr, modifiedPtr,
  1068.         copyUsedPtr)
  1069.     int         partFID;        /* Raw handle on disk. */
  1070.     Ofs_DomainHeader    *domainPtr;        /* Ptr to domain info. */
  1071.     int            fdNum;            /* File descriptor # to check.*/
  1072.     Fsdm_FileDescriptor    *fdPtr;            /* Ptr to file descriptor that
  1073.                          * are checking. */
  1074.     unsigned char     *newCylBitmapPtr;    /* Pointer to the disk block
  1075.                          * bit map. */
  1076.     int            *modifiedPtr;        /* TRUE => modified the file */
  1077.     Boolean        *copyUsedPtr;        /* TRUE => copy of fd was stored                          * somewhere. */
  1078.  {
  1079.     register int        *indexPtr;
  1080.     register int        i, j;
  1081.     static int             *dblIndirectBlock[FSDM_INDICES_PER_BLOCK];
  1082.     int                indBlock;
  1083.     int                lastBlock;
  1084.     int                lastFrag;
  1085.     int                tBlock;
  1086.     int                dirty;
  1087.     int                lastRealBlock;
  1088.     int                blockCount = 0;
  1089.     int                status = 0;
  1090.     Boolean            duplicate;
  1091.     int                virtualIndex;
  1092.  
  1093.     if (!(fdPtr->flags & FSDM_FD_ALLOC)) {
  1094.     return;
  1095.     }
  1096.     numFiles++;
  1097.     lastRealBlock = -1;
  1098.     /*
  1099.      * -1 is an empty file, anything less is an error.
  1100.      */
  1101.     if (fdPtr->lastByte < -1) {
  1102.     if (verbose || lastErrorFD != fdNum) {
  1103.         Output(stderr, "File %d has bogus size %d. Setting to -1.\n",
  1104.             fdNum, fdPtr->lastByte);
  1105.     }
  1106.     fdPtr->lastByte = -1;
  1107.     foundError = 1;
  1108.     *modifiedPtr = 1;
  1109.     }
  1110.     if (fdPtr->lastByte == -1) {
  1111.     lastBlock = -1;
  1112.     lastFrag = FS_FRAGMENTS_PER_BLOCK - 1;
  1113.     } else {
  1114.     lastBlock = fdPtr->lastByte / FS_BLOCK_SIZE;
  1115.     if (lastBlock < FSDM_NUM_DIRECT_BLOCKS) {
  1116.         lastFrag = (fdPtr->lastByte & FS_BLOCK_OFFSET_MASK) / FS_FRAGMENT_SIZE;
  1117.     } else {
  1118.         lastFrag = FS_FRAGMENTS_PER_BLOCK - 1;
  1119.     }
  1120.     }
  1121.  
  1122.     /*
  1123.      * First check direct blocks. Loop through them first and see if the 
  1124.      * file size corresponds to the number of blocks.
  1125.      */
  1126.     for (i = 0; i < FSDM_NUM_DIRECT_BLOCKS; i++) {
  1127.     if (i > lastBlock && fdPtr->direct[i] != FSDM_NIL_INDEX) {
  1128.         lastBlock++;
  1129.         fdPtr->lastByte += FS_BLOCK_SIZE;
  1130.         foundError = 1;
  1131.         *modifiedPtr = 1;
  1132.         if (lastFrag != FS_FRAGMENTS_PER_BLOCK - 1) {
  1133.         fdPtr->lastByte += (FS_FRAGMENTS_PER_BLOCK -1 - lastFrag) *
  1134.                    FS_FRAGMENT_SIZE;
  1135.         lastFrag = FS_FRAGMENTS_PER_BLOCK - 1;
  1136.         }
  1137.         if (verbose || lastErrorFD != fdNum) {
  1138.         Output(stderr,
  1139.     "Found a direct block beyond end of file %d. Increasing file size.\n",
  1140.             fdNum);
  1141.         lastErrorFD = fdNum;
  1142.         }
  1143.     }
  1144.     }
  1145.     for (i = 0; i < FSDM_NUM_DIRECT_BLOCKS; i++) {
  1146.     if (fileToPrint == fdNum) {
  1147.         Output(stderr, "File %d, d[%d] = %d.\n", fdNum, i, 
  1148.         fdPtr->direct[i]);
  1149.     }
  1150.     if (fdPtr->direct[i] != FSDM_NIL_INDEX) {
  1151.         if (blockToFind == fdPtr->direct[i]) {
  1152.         Output(stderr, "Block %d is d[%d] in file %d.\n", 
  1153.             fdPtr->direct[i], i, fdNum);
  1154.         }
  1155.         if (i == lastBlock) {
  1156.         status = MarkBitmap(fdNum, fdPtr->direct[i],
  1157.                     newCylBitmapPtr,
  1158.                     lastFrag + 1, domainPtr);
  1159.         if (status >= 0) {
  1160.             if (lastFrag + 1 != FS_FRAGMENTS_PER_BLOCK) {
  1161.             numFrags++;
  1162.             }
  1163.             blockCount += lastFrag + 1;
  1164.             numBlocks += lastFrag + 1;
  1165.         }
  1166.         } else {
  1167.         if (fdPtr->direct[i] & 
  1168.             (FS_FRAGMENTS_PER_BLOCK - 1)) {
  1169.             if (verbose || lastErrorFD != fdNum) {
  1170.             Output(stderr,
  1171.   "Block pointer %d invalid  in direct block %d of file %d. Block deleted.\n",
  1172.                     fdPtr->direct[i],i,fdNum);
  1173.             lastErrorFD = fdNum;
  1174.             }
  1175.             foundError = 1;
  1176.             status = -1;
  1177.         } else {
  1178.             status = MarkBitmap(fdNum, fdPtr->direct[i],
  1179.                     newCylBitmapPtr,
  1180.                     FS_FRAGMENTS_PER_BLOCK, domainPtr);
  1181.             if (status >= 0) {
  1182.             blockCount += FS_FRAGMENTS_PER_BLOCK;
  1183.             numBlocks += FS_FRAGMENTS_PER_BLOCK;
  1184.             }
  1185.         }
  1186.         }
  1187.         /*
  1188.          * Current block is also used by another file. Put info in copy
  1189.          * list so block is copied.
  1190.          */
  1191.         if (status == 1) {
  1192.         if (!tooBig) {
  1193.             AddToCopyList(FD,fdPtr,fdNum,0,i,DIRECT, 
  1194.                   (i == lastBlock) ? lastFrag + 1 :
  1195.                       FS_FRAGMENTS_PER_BLOCK,  copyUsedPtr);
  1196.         }
  1197.         }
  1198.         if (status < 0) {
  1199.         fdPtr->direct[i] = FSDM_NIL_INDEX;
  1200.         if (fdPtr->fileType == FS_DIRECTORY) {
  1201.             if (verbose || lastErrorFD != fdNum) {
  1202.             Output(stderr,
  1203.             "Hole in directory %d at direct block %d.\n", fdNum,
  1204.             i);
  1205.             lastErrorFD = fdNum;
  1206.             }
  1207.             AddToCopyList(FD,fdPtr,fdNum,0,i,DIRECT, 
  1208.                   (i == lastBlock) ? lastFrag + 1 :
  1209.                   FS_FRAGMENTS_PER_BLOCK,  copyUsedPtr);
  1210.         }
  1211.         } else {
  1212.         lastRealBlock = i;
  1213.         if (i == lastBlock) {
  1214.             break;
  1215.         }
  1216.         }
  1217.     } else if (fdPtr->fileType == FS_DIRECTORY) {
  1218.         if (verbose || lastErrorFD != fdNum) {
  1219.         Output(stderr, "Hole in directory %d at direct block %d.\n", 
  1220.         fdNum, i);
  1221.         lastErrorFD = fdNum;
  1222.         }
  1223.         AddToCopyList(FD,fdPtr,fdNum,0,i,DIRECT, 
  1224.               (i == lastBlock) ? lastFrag + 1 :
  1225.               FS_FRAGMENTS_PER_BLOCK,  copyUsedPtr);
  1226.     }
  1227.     }
  1228.     /*
  1229.      * Now check the singly indirect block.
  1230.      */
  1231.     if (fdPtr->indirect[0] == FSDM_NIL_INDEX) {
  1232.     if (fdPtr->fileType == FS_DIRECTORY && 
  1233.         lastBlock > FSDM_NUM_DIRECT_BLOCKS) {
  1234.         if (verbose || lastErrorFD != fdNum) {
  1235.         Output(stderr,
  1236.         "Hole in directory %d at single indirect block\n",
  1237.                    fdNum);
  1238.         lastErrorFD = fdNum;
  1239.         }
  1240.         AddToCopyList(FD,fdPtr,fdNum,0,FSDM_NUM_DIRECT_BLOCKS,INDIRECT, 
  1241.               FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1242.     }
  1243.     i += FSDM_INDICES_PER_BLOCK;
  1244.     } else {
  1245.     tBlock = i;
  1246.     status = ProcessIndirectBlock(fdNum, partFID,lastBlock, FALSE, fdPtr, 
  1247.                       &fdPtr->indirect[0], newCylBitmapPtr,
  1248.                       domainPtr,&tBlock, &dirty,
  1249.                       &lastRealBlock, modifiedPtr, &blockCount,
  1250.                       copyUsedPtr);
  1251.     i = tBlock;
  1252.     /*
  1253.      * We need to copy block
  1254.      */
  1255.     if (status == 1) {
  1256.         AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS, INDIRECT,
  1257.               FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1258.     }  
  1259.     if (status < 0) {
  1260.         if (verbose || lastErrorFD != fdNum) {
  1261.         Output(stderr, 
  1262.                 "Hole in directory %d at single indirect block\n",
  1263.                    fdNum);
  1264.         lastErrorFD = fdNum;
  1265.         }
  1266.         AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS, INDIRECT,
  1267.               FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1268.     } 
  1269.     }
  1270.     if (fdPtr->indirect[1] == FSDM_NIL_INDEX) {
  1271.     goto checkBlockCount;
  1272.     }
  1273.  
  1274.     /*
  1275.      * Now check doubly indirect blocks.
  1276.      */
  1277.     indBlock = fdPtr->indirect[1];
  1278.     if (indBlock & (FS_FRAGMENTS_PER_BLOCK - 1)) {
  1279.     if (verbose || lastErrorFD != fdNum) {
  1280.         Output(stderr, 
  1281.  "Doubly indirect block %d on non-block boundary in file %d.  Block deleted.\n",
  1282.               indBlock, fdNum);
  1283.         lastErrorFD = fdNum;
  1284.         setCheckedBit = FALSE;
  1285.     }
  1286.     foundError = 1;
  1287.     status = -1;
  1288.     } else {
  1289.     status = MarkBitmap(fdNum, PhysToVirt(domainPtr, indBlock),
  1290.         newCylBitmapPtr,
  1291.         FS_FRAGMENTS_PER_BLOCK, domainPtr);
  1292.     }
  1293.     if (status >= 0) {
  1294.     if (Disk_BlockRead(partFID, domainPtr, 
  1295.                indBlock / FS_FRAGMENTS_PER_BLOCK,
  1296.                1, (Address) dblIndirectBlock) < 0) {
  1297.         OutputPerror("CheckBlocks: Read failed");
  1298.         fdPtr->indirect[1] = FSDM_NIL_INDEX;
  1299.         *modifiedPtr = 1;
  1300.         goto truncFile;
  1301.     }
  1302.     /* 
  1303.      * Look over contents of block first and see if they make sense.
  1304.      */
  1305.     for (j = 0, indexPtr = (int *) dblIndirectBlock; 
  1306.          j < FSDM_INDICES_PER_BLOCK; 
  1307.          j++, indexPtr++) {
  1308.         if (*indexPtr != FSDM_NIL_INDEX) {
  1309.         virtualIndex = PhysToVirt(domainPtr, *indexPtr);
  1310.         if (virtualIndex < 0 || virtualIndex >= num1KBlocks) {
  1311.             if (verbose || lastErrorFD != fdNum) {
  1312.             Output(stderr, 
  1313.             "Double indirect block %d of file %d contains garbage index %d\n", 
  1314.                        indBlock, fdNum, *indexPtr);
  1315.             lastErrorFD = fdNum;
  1316.             }
  1317.             fdPtr->indirect[1] = FSDM_NIL_INDEX;
  1318.             setCheckedBit = FALSE;
  1319.             *modifiedPtr = 1;
  1320.             goto truncFile;
  1321.         } else if ( i + j * FSDM_INDICES_PER_BLOCK > lastBlock) {
  1322.             lastBlock = i + j * FSDM_INDICES_PER_BLOCK;
  1323.             fdPtr->lastByte += FS_BLOCK_SIZE * FSDM_INDICES_PER_BLOCK;
  1324.             *modifiedPtr = 1;
  1325.         }
  1326.  
  1327.         }
  1328.     }
  1329.     duplicate = FALSE;
  1330.     if (status == 1) {
  1331.         duplicate = TRUE;
  1332.         AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS + 1,
  1333.               DBL_INDIRECT,    FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1334.     }
  1335.     for (j = 0, indexPtr = (int *) dblIndirectBlock; 
  1336.          j < FSDM_INDICES_PER_BLOCK && i <= lastBlock; 
  1337.          j++, indexPtr++) {
  1338.         if (*indexPtr == FSDM_NIL_INDEX) {
  1339.         if (fdPtr->fileType == FS_DIRECTORY) {
  1340.             if (verbose || lastErrorFD != fdNum) {
  1341.             Output(stderr, 
  1342.             "Hole in directory %d in doubly indirect block\n",
  1343.                        fdNum);
  1344.             lastErrorFD = fdNum;
  1345.             }
  1346.             AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS + 1,
  1347.               DBL_INDIRECT, FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1348.         }
  1349.         i += FSDM_INDICES_PER_BLOCK;
  1350.         continue;
  1351.         }
  1352.         tBlock = i;
  1353.         status = ProcessIndirectBlock(fdNum, partFID, lastBlock, duplicate, 
  1354.                       fdPtr, indexPtr, newCylBitmapPtr,
  1355.                       domainPtr, &tBlock, &dirty,
  1356.                       &lastRealBlock, modifiedPtr, 
  1357.                       &blockCount, copyUsedPtr);
  1358.        i = tBlock;
  1359.        if (status < 0) {
  1360.         if (verbose || lastErrorFD != fdNum) {
  1361.             Output(stderr, 
  1362.             "Hole in directory %d in doubly indirect blocks (2)\n",
  1363.                        fdNum);
  1364.             lastErrorFD = fdNum;
  1365.         }
  1366.         AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS + 1,
  1367.               DBL_INDIRECT, FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1368.         }
  1369.     }
  1370.     if (status == 1 && !duplicate) {
  1371.         AddToCopyList(BLOCK, fdPtr, 0, indBlock, j, INDIRECT, 
  1372.               FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1373.     }
  1374.     if (dirty) {
  1375.         if (writeDisk) {
  1376.         if (Disk_BlockWrite(partFID, domainPtr, 
  1377.                indBlock / FS_FRAGMENTS_PER_BLOCK,
  1378.                1, (Address) dblIndirectBlock) < 0) {
  1379.             OutputPerror("CheckBlocks: Write failed");
  1380.             exit(EXIT_WRITE_FAILURE);
  1381.         }
  1382.         }
  1383.     }
  1384.     numBlocks += FS_FRAGMENTS_PER_BLOCK;
  1385.     blockCount += FS_FRAGMENTS_PER_BLOCK;
  1386.  
  1387.     } else {
  1388.     if (fdPtr->fileType == FS_DIRECTORY) {
  1389.         AddToCopyList(FD, fdPtr, fdNum, 0, FSDM_NUM_DIRECT_BLOCKS + 1,
  1390.               DBL_INDIRECT, FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1391.         } else {
  1392.         fdPtr->indirect[1] = FSDM_NIL_INDEX;
  1393.         *modifiedPtr = 1;
  1394.     }
  1395.     }
  1396.  
  1397.     if (lastRealBlock == lastBlock) {
  1398.     goto checkBlockCount;
  1399.     }
  1400.  
  1401. truncFile:
  1402.  
  1403.     if (lastRealBlock != -1) {
  1404.     fdPtr->lastByte = (lastRealBlock + 1) * FS_BLOCK_SIZE - 1;
  1405.     } else {
  1406.     fdPtr->lastByte = -1;
  1407.     }
  1408.     Output(stderr,"Truncating file %d to length %d\n", fdNum,
  1409.                  fdPtr->lastByte + 1);
  1410.     foundError = 1;
  1411.     *modifiedPtr = 1;
  1412.  
  1413. checkBlockCount:
  1414.  
  1415.     if (blockCount != fdPtr->numKbytes) {
  1416.     if (verbose || lastErrorFD != fdNum) {
  1417.         Output(stderr,
  1418.         "Block count corrected for file %d.  Is %d should be %d.\n", 
  1419.                fdNum, fdPtr->numKbytes, blockCount);
  1420.         lastErrorFD = fdNum;
  1421.     }
  1422.     fdPtr->numKbytes = blockCount;
  1423.     foundError = 1;
  1424.     *modifiedPtr = 1;
  1425.     }
  1426. }
  1427.  
  1428. /*
  1429.  *----------------------------------------------------------------------
  1430.  *
  1431.  * ProcessIndirectBlock --
  1432.  *
  1433.  *    Scan through the file descriptors in the indirect block and
  1434.  *    update the cylinder map to reflect which blocks are allocated.
  1435.  *
  1436.  * Results:
  1437.  *    -1 if found a hole in an indirect block for a directory
  1438.  *    1 if block is already in use
  1439.  *    0 otherwise.
  1440.  *
  1441.  * Side effects:
  1442.  *    None.
  1443.  *
  1444.  *----------------------------------------------------------------------
  1445.  */
  1446. int
  1447. ProcessIndirectBlock(fdNum, partFID,lastBlock,duplicate, fdPtr, blockNumPtr, 
  1448.              newCylBitmapPtr,domainPtr,fileBlockNumPtr, dirtyPtr,
  1449.              lastRealBlockPtr, modifiedPtr, blockCountPtr,
  1450.              copyUsedPtr)
  1451.     int            fdNum;          /* Number of file descriptor that 
  1452.                          indirect block is in. */
  1453.     register Fsdm_FileDescriptor    *fdPtr;      /* Actual file descriptor. */
  1454.     int            *blockNumPtr;      /* Pointer to indirect block number */
  1455.     unsigned    char     *newCylBitmapPtr; /* The cylinder bit map to set bits
  1456.                          in for allocated blocks. */
  1457.     int            partFID;      /* File id to use to read in indirect
  1458.                          blocks from disk. */
  1459.     Ofs_DomainHeader    *domainPtr;      /* Domain to read from. */
  1460.     int            lastBlock;      /* The last block in the file. */
  1461.     int            *fileBlockNumPtr; /* Pointer to file block number. */
  1462.     int            *dirtyPtr;      /* 1 if *blockNumPtr gets 
  1463.                          modified. */
  1464.     int            *lastRealBlockPtr; /* Pointer to the number of the last
  1465.                           valid block that was found for the
  1466.                           file. */
  1467.     int            *modifiedPtr;       /* 1 if the file descriptor
  1468.                           is modified. */
  1469.     int            *blockCountPtr;       /* Count of the number of blocks in
  1470.                         * the file. */
  1471.     Boolean        *copyUsedPtr;       /* TRUE => copy of fd was stored
  1472.                         * somewhere and should not be
  1473.                         * reused. */
  1474.     Boolean        duplicate;       /* TRUE => we are processing a 
  1475.                         * duplicate block, therefore all
  1476.                         * direct blocks will also be 
  1477.                         * duplicates. */
  1478. {
  1479.     static char        indirectBlock[FS_BLOCK_SIZE];
  1480.     int            *indexPtr;
  1481.     int            i;
  1482.     int            dirty = 0;
  1483.     int            status;
  1484.     int         tempFileBlock;
  1485.     Boolean        foundDuplicate = FALSE;
  1486.     int            zeroCount;
  1487.  
  1488.  
  1489.  
  1490.     if (*blockNumPtr & (FS_FRAGMENTS_PER_BLOCK - 1)) {
  1491.     if (verbose || lastErrorFD != fdNum) {
  1492.         Output(stderr, 
  1493.     "Indirect block on a non-block boundary for file %d.  Block deleted.\n",
  1494.                fdNum);
  1495.         lastErrorFD = fdNum;
  1496.     }
  1497.     foundError = 1;
  1498.     status = -1;
  1499.     } else {
  1500.     status = MarkBitmap(fdNum, PhysToVirt(domainPtr, *blockNumPtr), 
  1501.                 newCylBitmapPtr, 
  1502.                 FS_FRAGMENTS_PER_BLOCK, domainPtr);
  1503.     }
  1504.     if (status == 0) {
  1505.         /*
  1506.          * FIXME: need to be able to flag this as a bad block on error.
  1507.          */
  1508.     status = Disk_BlockRead(partFID, domainPtr, 
  1509.                        *blockNumPtr / FS_FRAGMENTS_PER_BLOCK, 1, 
  1510.                    (Address) indirectBlock);
  1511.     if (status < 0) {
  1512.         OutputPerror("ProcessIndirectBlock: Read failed");
  1513.     }
  1514.     } else if (status == 1 ) {
  1515.     foundDuplicate = TRUE;
  1516.     }
  1517.     if (status < 0) {
  1518.     if (verbose || lastErrorFD != fdNum) {
  1519.         Output(stderr,
  1520.         "Indirect block (%d) unreadable for file #%d.  Block deleted.\n", 
  1521.                *blockNumPtr, fdNum);
  1522.         lastErrorFD = fdNum;
  1523.     }
  1524.     *fileBlockNumPtr += FSDM_INDICES_PER_BLOCK;
  1525.     *blockNumPtr = FSDM_NIL_INDEX;
  1526.     *dirtyPtr = 1;
  1527.     *modifiedPtr = 1;
  1528.     setCheckedBit = FALSE;
  1529.     return(0);
  1530.     } else {
  1531.     *dirtyPtr = 0;
  1532.     }
  1533.     /* 
  1534.      * Look over contents of block first and see if they make sense.
  1535.      */
  1536.     zeroCount = 0;
  1537.     for (i = 0, indexPtr = (int *) indirectBlock,
  1538.      tempFileBlock = *fileBlockNumPtr; 
  1539.      i < FSDM_INDICES_PER_BLOCK; 
  1540.      i++, tempFileBlock++, indexPtr++) {
  1541.     if (*indexPtr != FSDM_NIL_INDEX) {
  1542.         if (*indexPtr == 0) {
  1543.         zeroCount++;
  1544.         continue;
  1545.         }
  1546.         if (*indexPtr == blockToFind) {
  1547.         Output(stderr, "Block %d is i[%d] in file %d.\n",
  1548.             *indexPtr, i, fdNum);
  1549.         }
  1550.         if (*indexPtr < 0 || *indexPtr >= num1KBlocks) {
  1551.         if (verbose || lastErrorFD != fdNum) {
  1552.             Output(stderr, 
  1553.             "Indirect block %d of file %d contains garbage index %d\n", 
  1554.                    *blockNumPtr, fdNum, *indexPtr);
  1555.             lastErrorFD = fdNum;
  1556.             setCheckedBit = FALSE;
  1557.         }
  1558.             *fileBlockNumPtr += FSDM_INDICES_PER_BLOCK;
  1559.             *blockNumPtr = FSDM_NIL_INDEX;
  1560.             *dirtyPtr = 1;
  1561.             *modifiedPtr = 1;
  1562.             foundError = 1;
  1563.         if (fdPtr->fileType == FS_DIRECTORY) {
  1564.            return(-1);
  1565.         } else {
  1566.            return(0);
  1567.             }
  1568.          } else if (tempFileBlock > lastBlock) {
  1569.          lastBlock = tempFileBlock;
  1570.          fdPtr->lastByte = tempFileBlock * FS_BLOCK_SIZE -1;
  1571.          *modifiedPtr = 1;
  1572.          }
  1573.      }
  1574.      }
  1575.     if (zeroCount == FSDM_INDICES_PER_BLOCK) {
  1576.     if (verbose || lastErrorFD != fdNum) {
  1577.         Output(stderr, "Indirect block %d is all zeros.\n", 
  1578.                *blockNumPtr, *indexPtr);
  1579.         lastErrorFD = fdNum;
  1580.     }
  1581.     *fileBlockNumPtr += FSDM_INDICES_PER_BLOCK;
  1582.     *blockNumPtr = FSDM_NIL_INDEX;
  1583.     *dirtyPtr = 1;
  1584.     *modifiedPtr = 1;
  1585.     foundError = 1;
  1586.     setCheckedBit = FALSE;
  1587.     if (fdPtr->fileType == FS_DIRECTORY) {
  1588.        return(-1);
  1589.     } else {
  1590.        return(0);
  1591.     }
  1592.     }
  1593.     numBlocks += FS_FRAGMENTS_PER_BLOCK;
  1594.     *blockCountPtr += FS_FRAGMENTS_PER_BLOCK;
  1595.      for (i = 0, indexPtr = (int *) indirectBlock; 
  1596.      i < FSDM_INDICES_PER_BLOCK && *fileBlockNumPtr <= lastBlock; 
  1597.      i++, (*fileBlockNumPtr)++, indexPtr++) {
  1598.  
  1599.      if (*indexPtr == FSDM_NIL_INDEX) {
  1600.         if (fdPtr->fileType == FS_DIRECTORY) {
  1601.         AddToCopyList(BLOCK, fdPtr, 0, 
  1602.                 *blockNumPtr, i, DIRECT, 
  1603.                  FS_FRAGMENTS_PER_BLOCK, 
  1604.                  copyUsedPtr);
  1605.         }
  1606.         continue;
  1607.      }
  1608.      if (*indexPtr & (FS_FRAGMENTS_PER_BLOCK - 1)) {
  1609.          if (verbose || lastErrorFD != fdNum) {
  1610.          Output(stderr, 
  1611.          "Non-direct block fragmented for file %d.  Block deleted.\n",
  1612.                fdNum);
  1613.          lastErrorFD = fdNum;
  1614.          }
  1615.          foundError = 1;
  1616.          status = -1;
  1617.      } else {
  1618.          status = MarkBitmap(fdNum, *indexPtr, 
  1619.                 newCylBitmapPtr,
  1620.                 FS_FRAGMENTS_PER_BLOCK, domainPtr);
  1621.      }
  1622.     /* 
  1623.      * One of the direct blocks is a duplicate.
  1624.      */
  1625.     if (status == 1 && !duplicate) {
  1626.         AddToCopyList(BLOCK, fdPtr , 0, *blockNumPtr, 
  1627.              i, DIRECT, 
  1628.              FS_FRAGMENTS_PER_BLOCK, copyUsedPtr);
  1629.     }
  1630.     if (status >= 0) {
  1631.         *blockCountPtr += FS_FRAGMENTS_PER_BLOCK;
  1632.         numBlocks += FS_FRAGMENTS_PER_BLOCK;
  1633.         *lastRealBlockPtr = *fileBlockNumPtr;
  1634.     } else {
  1635.         *indexPtr = FSDM_NIL_INDEX;
  1636.         dirty = 1;
  1637.     }
  1638.     }
  1639.     if (dirty) {
  1640.     if (writeDisk) {
  1641.         if (Disk_BlockWrite(partFID, domainPtr, 
  1642.                 *blockNumPtr / FS_FRAGMENTS_PER_BLOCK,
  1643.                 1, (Address) indirectBlock) < 0) {
  1644.         OutputPerror("ProcessIndirectBlock: Write failed");
  1645.         exit(EXIT_WRITE_FAILURE);
  1646.         }
  1647.     }
  1648.     }
  1649.     if (foundDuplicate) {
  1650.     return 1;
  1651.     }
  1652.     return(0);
  1653. }
  1654.  
  1655.  
  1656.  
  1657. /*
  1658.  *----------------------------------------------------------------------
  1659.  *
  1660.  * RelocateFD ---
  1661.  *
  1662.  *    Allocate a new file descriptor as close to the old one as possible.
  1663.  *    This is used to relocate descriptors in blocks that get I/O errors.
  1664.  *    This code is based on the kernel routine FsGetNewFileNumber.
  1665.  *    
  1666.  * Results:
  1667.  *    None.
  1668.  *
  1669.  * Side effects:
  1670.  *    The new descriptor is marked as allocated in the bitmap.
  1671.  *
  1672.  *----------------------------------------------------------------------
  1673.  */
  1674.  
  1675. void
  1676. RelocateFD(domainPtr, descInfoPtr, relocPtr)
  1677.     register Ofs_DomainHeader *domainPtr;    /* Domain to allocate the file 
  1678.                      * descriptor out of. */
  1679.     FdInfo *descInfoPtr;        /* information for each file
  1680.                      * descriptor */
  1681.     RelocListElement *relocPtr;        /* Pointer to information for old
  1682.                      * descriptor. */
  1683. {
  1684.     register int            i;
  1685.     register int        j;
  1686.     int                startByte;
  1687.     register unsigned char     *bitmapPtr;
  1688.     register unsigned char     *bitmaskPtr;
  1689.     int                   found = 0;
  1690.     static int               outOfDescriptors = 0;
  1691.     int                   descBytes;
  1692.  
  1693.     /*
  1694.      * If we can't relocate it, chuck it.
  1695.      */
  1696.     if (outOfDescriptors) {
  1697.     descInfoPtr[relocPtr->origFdNum].flags |= FD_UNREADABLE;
  1698.     return;
  1699.     }
  1700.  
  1701.     /*
  1702.      * Linear search forward the bit map a byte at a time.
  1703.      */
  1704.     startByte = relocPtr->origFdNum / BITS_PER_BYTE;
  1705.     bitmapPtr = &fdBitmapPtr[startByte];
  1706.     descBytes = domainPtr->numFileDesc >> 3;
  1707.     i = startByte;
  1708.     do {
  1709.     if (*bitmapPtr != 0xff) {
  1710.         found = 1;
  1711.         break;
  1712.     }
  1713.     i++;
  1714.     if (i == descBytes) {
  1715.         i = 0;
  1716.         bitmapPtr = fdBitmapPtr;
  1717.     } else {
  1718.         bitmapPtr++;
  1719.     }
  1720.     } while (i != startByte);
  1721.  
  1722.     if (!found) {
  1723.     /*
  1724.      * Couldn't relocate it, so throw it away and pretend we couldn't
  1725.      * recover it.
  1726.      */
  1727.     if (!outOfDescriptors) {
  1728.         Output(stderr, "RelocateFD: out of file descriptors.\n");
  1729.         abort();
  1730.     } else {
  1731.         outOfDescriptors = 1;
  1732.     }
  1733.     descInfoPtr[relocPtr->origFdNum].flags |= FD_UNREADABLE;
  1734.     return;
  1735.     }
  1736.  
  1737.     /*
  1738.      * Now find which file descriptor is free within the byte.
  1739.      */
  1740.     for (j = 0, bitmaskPtr = bitmasks; 
  1741.      j < 8 && (*bitmapPtr & *bitmaskPtr) != 0; 
  1742.      j++, bitmaskPtr++) {
  1743.     }
  1744.     relocPtr->newFdNum = i * 8 + j;
  1745.     if (verbose || lastErrorFD != relocPtr->origFdNum) {
  1746.     Output(stderr,
  1747.     "Fd %d relocated to %d.\n",relocPtr->origFdNum,relocPtr->newFdNum);
  1748.     lastErrorFD = relocPtr->origFdNum;
  1749.     }
  1750.     *bitmapPtr |= *bitmaskPtr;
  1751. }
  1752.  
  1753.  
  1754. /*
  1755.  *----------------------------------------------------------------------
  1756.  *
  1757.  *  CopyBlock ---
  1758.  *
  1759.  *    Copy a block and fix up pointers to it.  FillNewBlock does the
  1760.  *    real work. CopyBlock gets the block info off the copyList and
  1761.  *    calls FillNewBlock.
  1762.  *         This procedure is also used to fill in holes in directories.
  1763.  * Results:
  1764.  *    0  - ok
  1765.  *    -1 -  disk is full
  1766.  *    -2 - some other error
  1767.  *
  1768.  * Side effects:
  1769.  *    Parent (either fd or indirect block) is changed to point to copy.
  1770.  *
  1771.  *----------------------------------------------------------------------
  1772.  */
  1773. int
  1774. CopyBlock(domainPtr, descInfoPtr, partFID, bitmapPtr, copyPtr)
  1775.     register Ofs_DomainHeader     *domainPtr;    /* Domain to allocate the file 
  1776.                          * descriptor out of. */
  1777.     FdInfo             *descInfoPtr;    /* information for each file
  1778.                          * descriptor */
  1779.     int                 partFID;    /* File id to read from disk */
  1780.     u_char            *bitmapPtr;    /* Cylinder bitmap pointer */
  1781.     CopyListElement         *copyPtr;    /* Pointer to information for 
  1782.                          * block to be copied */
  1783. {
  1784.     int            blockNum;
  1785.     int            parentBlockNum;
  1786.     int            *blockNumPtr;
  1787.     Fsdm_FileDescriptor    *fdPtr = NULL;
  1788.     int            fdNum;
  1789.     static int         block[FSDM_INDICES_PER_BLOCK];
  1790.     int            status;
  1791.  
  1792.  
  1793.  
  1794.     fdPtr = copyPtr->fdPtr;
  1795.     if (copyPtr->parentType == FD) {
  1796.     fdNum = copyPtr->parentNum;
  1797.     switch (copyPtr->blockType) {
  1798.         case DIRECT: 
  1799.         blockNumPtr = &fdPtr->direct[copyPtr->index];
  1800.         break;
  1801.         case INDIRECT:
  1802.         blockNumPtr = &fdPtr->indirect[0];
  1803.         break;
  1804.         case DBL_INDIRECT:
  1805.         blockNumPtr = &fdPtr->indirect[1];
  1806.         break;
  1807.     }
  1808.     } else {
  1809.     parentBlockNum = copyPtr->parentNum;
  1810.     status = Disk_BlockRead(partFID, domainPtr, 
  1811.                        parentBlockNum / FS_FRAGMENTS_PER_BLOCK, 1, 
  1812.                    (Address) block);
  1813.     if (status < 0) {
  1814.         OutputPerror(
  1815.         "CopyBlock: Previously readable block %d unreadable.\n",
  1816.         parentBlockNum);
  1817.         foundError = 1;
  1818.         return -2;
  1819.     }
  1820.     blockNumPtr = &(block[copyPtr->index]);
  1821.     }
  1822.     blockNum = *blockNumPtr;
  1823.     status = FillNewBlock(blockNum, copyPtr->blockType, copyPtr->fragments,
  1824.               fdPtr, domainPtr, descInfoPtr, partFID, 
  1825.               bitmapPtr, blockNumPtr);
  1826.     /* 
  1827.      * If status is -1 then disk is full so stop trying to copy blocks.
  1828.      */
  1829.     if (status == -1) {
  1830.     Output(stderr,"fscheck: disk is full.\n");
  1831.     foundError = 1;
  1832.     errorType = EXIT_DISK_FULL;
  1833.     }
  1834.     if (!writeDisk) {
  1835.     return 0;
  1836.     }
  1837.     if (copyPtr->parentType == FD) {
  1838.     if (!(descInfoPtr[fdNum].flags & (ON_MOD_LIST | FD_RELOCATE))) {
  1839.          ModListElement    *modElemPtr;
  1840.  
  1841.         Alloc(modElemPtr,ModListElement,1);
  1842.         if (tooBig) {
  1843.         return 0;
  1844.         }
  1845.         descInfoPtr[fdNum].flags |= ON_MOD_LIST;
  1846.         modElemPtr->fdNum = fdNum;
  1847.         modElemPtr->fdPtr = fdPtr;
  1848.         List_Insert((List_Links *)modElemPtr, LIST_ATREAR(modList));
  1849.     }
  1850.     } else {
  1851.     if (Disk_BlockWrite(partFID, domainPtr,
  1852.                 parentBlockNum / FS_FRAGMENTS_PER_BLOCK,
  1853.                 1, (Address) block) < 0) {
  1854.         OutputPerror("CopyBlock: Unable to write block %d.\n",
  1855.         parentBlockNum);
  1856.         foundError = 1;
  1857.         return 0;
  1858.     }
  1859.     }
  1860.     return 0;
  1861. }
  1862.  
  1863. /*
  1864.  *----------------------------------------------------------------------
  1865.  *
  1866.  *  FillNewBlock ---
  1867.  *
  1868.  *    Looks through the bitmap for a free block and copies the given block
  1869.  *    into it. If the given block is an indirect block then we recurse to
  1870.  *    also copy all included blocks. Note that we only look for an empty
  1871.  *    full block (4 fragments). This may lead to a disk full error when
  1872.  *    the disk really isn't full.
  1873.  * 
  1874.  * Results:
  1875.  *    0 - ok
  1876.  *    -1 - disk full
  1877.  *    -2 - some other error
  1878.  *
  1879.  * Side effects:
  1880.  *    A block in the bitmap is marked as in use.
  1881.  *
  1882.  *----------------------------------------------------------------------
  1883.  */
  1884. int
  1885. FillNewBlock(blockNum, blockType, fragments, fdPtr, domainPtr, 
  1886.              descInfoPtr, partFID, bitmapPtr, newBlockNumPtr)
  1887.     int         blockNum;        /* Block number of block to be
  1888.                          * copied. */
  1889.     BlockIndexType     blockType;        /* Type of block to be copied
  1890.                          */
  1891.     int         fragments;        /* Number of fragments in block
  1892.                          */
  1893.     Fsdm_FileDescriptor    *fdPtr;            /* Ptr at fd of file. */
  1894.     Ofs_DomainHeader    *domainPtr;           /* Ptr at domain info */
  1895.     FdInfo        *descInfoPtr;        /* Descriptor info array */
  1896.     int            partFID;        /* File id to read from disk */
  1897.     u_char        *bitmapPtr;        /* Cylinder data block bitmap */
  1898.     int         *newBlockNumPtr;    /* Block number of new allocated
  1899.                          * block */
  1900. {
  1901.     char        block[FS_BLOCK_SIZE];
  1902.     int            *indBlock;
  1903.     int            newBlockNum;
  1904.     int            i;
  1905.     int            status;
  1906.     int            vBlockNum;
  1907.  
  1908.     if (blockNum != FSDM_NIL_INDEX) { 
  1909.     vBlockNum = (blockType == DIRECT) ? blockNum : 
  1910.             PhysToVirt(domainPtr,blockNum);
  1911.     status = Disk_FragRead(partFID, domainPtr, 
  1912.                 VirtToPhys(domainPtr,vBlockNum), 
  1913.                 fragments, (Address) block);
  1914.     if (status < 0) {
  1915.         OutputPerror("FillNewBlock: Unable to read block %d to copy.\n",
  1916.              vBlockNum);
  1917.         foundError = 1;
  1918.         return -2;
  1919.     }
  1920.     } else if (fdPtr->fileType == FS_DIRECTORY) {
  1921.     vBlockNum = -1;
  1922.     bzero(block, FS_BLOCK_SIZE);
  1923.     } else {
  1924.     Output(stderr,"Internal error: trying to copy null index.\n");
  1925.     return -2;
  1926.     }
  1927.     newBlockNum = AllocBlock(domainPtr,fragments,bitmapPtr);
  1928.     if (newBlockNum == -1) {
  1929.     /*
  1930.      * Disk is full
  1931.      */
  1932.     return -1;
  1933.     }
  1934.     if (blockType != DIRECT) {
  1935.     BlockIndexType entryType;
  1936.  
  1937.     if (blockType == INDIRECT) {
  1938.         entryType = DIRECT;
  1939.     } else {
  1940.         entryType = INDIRECT;
  1941.     }
  1942.     for (i = 0,indBlock = (int *)block; 
  1943.          i < FSDM_INDICES_PER_BLOCK; 
  1944.          i++,indBlock++){
  1945.  
  1946.          if (*indBlock != FSDM_NIL_INDEX || 
  1947.          fdPtr->fileType == FS_DIRECTORY) {
  1948.  
  1949.         status = FillNewBlock(*indBlock, entryType, 
  1950.                       FS_FRAGMENTS_PER_BLOCK, fdPtr, domainPtr, 
  1951.                       descInfoPtr, partFID, bitmapPtr,
  1952.                       indBlock);
  1953.         }
  1954.         if (status == -1) {
  1955.         break;
  1956.         } 
  1957.     }
  1958.     /*
  1959.      * If the block number is nil then we are filling in a hole in a directory.
  1960.      * Fill out the disk block with empty entries.
  1961.      */
  1962.     } else if (blockNum == FSDM_NIL_INDEX) {
  1963.     Fslcl_DirEntry *entryPtr;
  1964.     int i;
  1965.  
  1966.     bzero( block, FS_BLOCK_SIZE);
  1967.  
  1968.     for (entryPtr = (Fslcl_DirEntry *)block, i = 0; 
  1969.          i < fragments * FS_FRAGMENT_SIZE  / FSLCL_DIR_BLOCK_SIZE;
  1970.          i++,entryPtr=(Fslcl_DirEntry *)((int)entryPtr + FSLCL_DIR_BLOCK_SIZE)) {
  1971.          entryPtr->fileNumber = 0;
  1972.          entryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  1973.          entryPtr->nameLength = 0;
  1974.     }
  1975.     }
  1976.     if (writeDisk) {
  1977.     status = Disk_FragWrite(partFID, domainPtr,
  1978.                  VirtToPhys(domainPtr, newBlockNum),
  1979.                  fragments,
  1980.                     (Address) block);
  1981.     if (status < 0) {
  1982.         OutputPerror("FillNewBlock: Unable to write to new block %d.\n",
  1983.              newBlockNum);
  1984.         foundError = 1;
  1985.         return -2;
  1986.     }
  1987.     }
  1988.     *newBlockNumPtr = (blockType == DIRECT) ? newBlockNum :
  1989.               VirtToPhys(domainPtr, newBlockNum);
  1990.     if (verbose) {
  1991.     if (vBlockNum != -1) {
  1992.         Output(stderr,"Copied %d fragments starting at %d to %d.\n", 
  1993.         fragments, vBlockNum, newBlockNum);
  1994.     } else {
  1995.         Output(stderr,"Added new directory block %d.\n", newBlockNum);
  1996.     }
  1997.     }
  1998.     return 0;
  1999. }
  2000. @
  2001.  
  2002.  
  2003. 1.37
  2004. log
  2005. @puts output in .fscheck.out even if disk already checked, updated ot
  2006. ofs
  2007. @
  2008. text
  2009. @d17 1
  2010. a17 1
  2011. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fscheck.c,v 1.36 90/10/10 15:28:44 mendel Exp $ SPRITE (Berkeley)";
  2012. a166 1
  2013.     int        firstPartFID;
  2014. a260 5
  2015.     firstPartFID = open(firstPartitionName, O_RDONLY);
  2016.     if (firstPartFID < 0) {
  2017.     OutputPerror("fscheck: Can't open first partition");
  2018.     exit(EXIT_HARD_ERROR);
  2019.     }
  2020. d278 1
  2021. a278 1
  2022.     CheckFilesystem(firstPartFID, partFID, partition);
  2023. a282 1
  2024.     (void)close(firstPartFID);
  2025. d346 1
  2026. a346 2
  2027. CheckFilesystem(firstPartFID, partFID, partition)
  2028.     int firstPartFID;    /* Handle on the first partition of the disk */
  2029. d385 1
  2030. a385 1
  2031.     labelPtr = Disk_ReadLabel(firstPartFID);
  2032. d418 1
  2033. a418 1
  2034.         fstat(firstPartFID, &attrs);
  2035. @
  2036.  
  2037.  
  2038. 1.36
  2039. log
  2040. @Changes to reflect new OFS file system names.
  2041. @
  2042. text
  2043. @d17 1
  2044. a17 1
  2045. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fscheck.c,v 1.35 90/10/10 11:21:46 jhh Exp Locker: mendel $ SPRITE (Berkeley)";
  2046. d490 1
  2047. @
  2048.  
  2049.  
  2050. 1.35
  2051. log
  2052. @now can do raw output on any partition, fixed bug with ".."
  2053. @
  2054. text
  2055. @d17 1
  2056. a17 1
  2057. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck.new/RCS/fscheck.c,v 1.34 90/05/01 15:36:36 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  2058. d37 1
  2059. a37 1
  2060. Fsdm_DomainHeader  *domainPtr;
  2061. d864 1
  2062. a864 1
  2063.     Fsdm_DomainHeader    *domainPtr;        /* Ptr to domain info. */
  2064. d1253 1
  2065. a1253 1
  2066.     Fsdm_DomainHeader    *domainPtr;      /* Domain to read from. */
  2067. d1471 1
  2068. a1471 1
  2069.     register Fsdm_DomainHeader *domainPtr;    /* Domain to allocate the file 
  2070. d1569 1
  2071. a1569 1
  2072.     register Fsdm_DomainHeader     *domainPtr;    /* Domain to allocate the file 
  2073. d1688 1
  2074. a1688 1
  2075.     Fsdm_DomainHeader    *domainPtr;           /* Ptr at domain info */
  2076. @
  2077.  
  2078.  
  2079. 1.34
  2080. log
  2081. @ported to new Disk library
  2082. @
  2083. text
  2084. @d17 1
  2085. a17 1
  2086. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fscheck.c,v 1.33 90/02/14 15:55:20 jhh Exp $ SPRITE (Berkeley)";
  2087. d40 1
  2088. d64 1
  2089. a64 1
  2090. int rootPart = FALSE;
  2091. d104 2
  2092. a109 2
  2093.     {OPT_TRUE, "rootPart", (Address)&rootPart,
  2094.     "Partition being processed is the root partition"},    
  2095. d189 1
  2096. a189 1
  2097.     } else if (!rootPart) {
  2098. d208 1
  2099. a208 1
  2100. "Maximum buffer size allowed when processing root partition is %d bytes.\n",
  2101. d216 1
  2102. a216 1
  2103.     if (rootPart) {
  2104. d292 3
  2105. @
  2106.  
  2107.  
  2108. 1.33
  2109. log
  2110. @support for no recheck on reboot
  2111. @
  2112. text
  2113. @d17 1
  2114. a17 1
  2115. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fscheck.c,v 1.32 89/10/03 17:47:12 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  2116. a21 1
  2117. #include "diskUtils.h"
  2118. d354 1
  2119. a354 1
  2120.     Disk_Info               *diskInfoPtr;
  2121. d389 3
  2122. a391 3
  2123.     diskInfoPtr = Disk_ReadDiskInfo(firstPartFID, partition);
  2124.     if (diskInfoPtr == (Disk_Info *) NULL) {
  2125.     Output(stderr, "CheckFilesystem: Could not read basic disk info\n");
  2126. a395 2
  2127.     AllocByte(domainPtr,Fsdm_DomainHeader,diskInfoPtr->numDomainSectors *
  2128.                          DEV_BYTES_PER_SECTOR);
  2129. d401 5
  2130. a405 2
  2131.     ReadDomainHeader(partFID, diskInfoPtr, domainPtr);
  2132.  
  2133. d480 1
  2134. a480 1
  2135.     status = RecoveryCheck(partFID, diskInfoPtr);
  2136. d820 5
  2137. a824 1
  2138.     WriteDomainHeader(partFID, diskInfoPtr, domainPtr);
  2139. d835 1
  2140. a835 1
  2141.     WriteSummaryInfo(partFID, diskInfoPtr, domainPtr, 
  2142. @
  2143.  
  2144.  
  2145. 1.32
  2146. log
  2147. @added device prefix to all output lines
  2148. @
  2149. text
  2150. @d17 1
  2151. a17 1
  2152. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.31 89/10/03 11:08:59 jhh Exp $ SPRITE (Berkeley)";
  2153. d76 2
  2154. d109 1
  2155. a109 1
  2156.     "Partition being processed is root partition"},    
  2157. d126 4
  2158. d192 2
  2159. a193 1
  2160.         OutputPerror("fscheck: Can't open output file.");
  2161. a211 1
  2162.     Output(stderr, "Buffer size is %d.\n", bufferSize);
  2163. d216 3
  2164. a218 1
  2165.     Output(stderr,"      \n");
  2166. d223 3
  2167. a225 1
  2168.     Output(stderr,"%s\n",timeString);
  2169. a283 3
  2170.     if (!silent) {
  2171.     Output(stderr, "Checking %s.\n", partitionName);
  2172.     }
  2173. d475 1
  2174. a475 1
  2175.      * Check the disk to make sure that it has safely been synced.
  2176. d481 7
  2177. a487 1
  2178.  
  2179. d1070 1
  2180. d1104 1
  2181. d1314 1
  2182. d1342 1
  2183. d1372 1
  2184. @
  2185.  
  2186.  
  2187. 1.31
  2188. log
  2189. @new scsi disk mapping
  2190. @
  2191. text
  2192. @d17 1
  2193. a17 1
  2194. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.30 89/09/25 16:41:03 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  2195. d205 1
  2196. a205 1
  2197.     printf("Buffer size is %d.\n", bufferSize);
  2198. d214 2
  2199. a215 1
  2200.     Output(stderr,"***** Fscheck *****\n%s",timeString);
  2201. d713 1
  2202. a713 1
  2203.         Output(stderr, "\nTraversing directory tree:\n\n");
  2204. d720 1
  2205. a720 1
  2206.            "\nNOT traversing directory tree because heap limit exceeded.\n"
  2207. d727 1
  2208. a727 1
  2209.     Output(stderr, "\nComparing old and new data block bit maps:\n");
  2210. d1084 3
  2211. a1086 2
  2212.             Output(stderr, "Double indirect block %d contains garbage index %d\n", 
  2213.                        indBlock, *indexPtr);
  2214. d1322 3
  2215. a1324 2
  2216.             Output(stderr, "Indirect block %d contains garbage index %d\n", 
  2217.                    *blockNumPtr, *indexPtr);
  2218. @
  2219.  
  2220.  
  2221. 1.30
  2222. log
  2223. @Uses new fs module structure
  2224. @
  2225. text
  2226. @d17 1
  2227. a17 1
  2228. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.29 89/08/25 22:24:25 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  2229. d74 2
  2230. d120 4
  2231. d499 1
  2232. d513 1
  2233. a513 1
  2234.                    domainPtr->fileDescOffset + i,
  2235. d521 2
  2236. a522 2
  2237.                           domainPtr->fileDescOffset + i,
  2238.                           (Address) block);
  2239. d551 5
  2240. a555 2
  2241.              "File %d has an invalid magic number and is being reset.\n",
  2242.                     fdNum);
  2243. d651 1
  2244. a651 1
  2245.                     domainPtr->fileDescOffset + i,
  2246. d918 4
  2247. d923 4
  2248. d1313 4
  2249. @
  2250.  
  2251.  
  2252. 1.29
  2253. log
  2254. @Added ability to modify host id in domain header.
  2255. @
  2256. text
  2257. @d17 1
  2258. a17 1
  2259. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.28 89/07/31 17:43:27 jhh Exp $ SPRITE (Berkeley)";
  2260. d38 1
  2261. a38 1
  2262. FsDomainHeader  *domainPtr;
  2263. d193 1
  2264. a193 1
  2265.     if (bufferSize > FS_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE) {
  2266. d196 1
  2267. a196 1
  2268.         FS_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE);
  2269. d349 1
  2270. a349 1
  2271.     FsFileDescriptor        *fdPtr;
  2272. d361 1
  2273. a361 1
  2274.     FsFileDescriptor        *fdCopyPtr = NULL;
  2275. d383 1
  2276. a383 1
  2277.     AllocByte(domainPtr,FsDomainHeader,diskInfoPtr->numDomainSectors *
  2278. d480 2
  2279. a481 2
  2280.     numFileDescBlocks = (domainPtr->numFileDesc + FS_FILE_DESC_PER_BLOCK - 1) / 
  2281.         FS_FILE_DESC_PER_BLOCK;
  2282. d538 1
  2283. a538 1
  2284.             fdPtr = (FsFileDescriptor *)    
  2285. d540 2
  2286. a541 2
  2287.                 FS_MAX_FILE_DESC_SIZE];
  2288.              if (fdPtr->magic != FS_FD_MAGIC) {
  2289. d558 1
  2290. a558 1
  2291.             Alloc(fdCopyPtr,FsFileDescriptor,1);
  2292. d564 1
  2293. a564 1
  2294.               sizeof(FsFileDescriptor));
  2295. d570 1
  2296. a570 1
  2297.                 (fdPtr->flags & FS_FD_ALLOC)) {
  2298. d593 1
  2299. a593 1
  2300.             if (fdPtr->flags & FS_FD_ALLOC) {
  2301. d606 1
  2302. a606 1
  2303.                        fdNum == FS_BAD_BLOCK_FILE_NUMBER &&
  2304. d611 1
  2305. a611 1
  2306.             if ((badBlockInit && fdNum == FS_BAD_BLOCK_FILE_NUMBER) ||
  2307. d614 1
  2308. a614 1
  2309.                 fdNum == FS_BAD_BLOCK_FILE_NUMBER) {
  2310. d618 1
  2311. a618 1
  2312.             ClearFd(fdMagicOkay ? FS_FD_ALLOC : FS_FD_FREE, 
  2313. d629 1
  2314. a629 1
  2315.                   sizeof(FsFileDescriptor));
  2316. d832 1
  2317. a832 1
  2318.     FsDomainHeader    *domainPtr;        /* Ptr to domain info. */
  2319. d834 1
  2320. a834 1
  2321.     FsFileDescriptor    *fdPtr;            /* Ptr to file descriptor that
  2322. d843 1
  2323. a843 1
  2324.     static int             *dblIndirectBlock[FS_INDICES_PER_BLOCK];
  2325. d855 1
  2326. a855 1
  2327.     if (!(fdPtr->flags & FS_FD_ALLOC)) {
  2328. d877 1
  2329. a877 1
  2330.     if (lastBlock < FS_NUM_DIRECT_BLOCKS) {
  2331. d888 2
  2332. a889 2
  2333.     for (i = 0; i < FS_NUM_DIRECT_BLOCKS; i++) {
  2334.     if (i > lastBlock && fdPtr->direct[i] != FS_NIL_INDEX) {
  2335. d907 2
  2336. a908 2
  2337.     for (i = 0; i < FS_NUM_DIRECT_BLOCKS; i++) {
  2338.     if (fdPtr->direct[i] != FS_NIL_INDEX) {
  2339. d953 1
  2340. a953 1
  2341.         fdPtr->direct[i] = FS_NIL_INDEX;
  2342. d985 1
  2343. a985 1
  2344.     if (fdPtr->indirect[0] == FS_NIL_INDEX) {
  2345. d987 1
  2346. a987 1
  2347.         lastBlock > FS_NUM_DIRECT_BLOCKS) {
  2348. d994 1
  2349. a994 1
  2350.         AddToCopyList(FD,fdPtr,fdNum,0,FS_NUM_DIRECT_BLOCKS,INDIRECT, 
  2351. d997 1
  2352. a997 1
  2353.     i += FS_INDICES_PER_BLOCK;
  2354. d1010 1
  2355. a1010 1
  2356.         AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS, INDIRECT,
  2357. d1020 1
  2358. a1020 1
  2359.         AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS, INDIRECT,
  2360. d1024 1
  2361. a1024 1
  2362.     if (fdPtr->indirect[1] == FS_NIL_INDEX) {
  2363. d1051 1
  2364. a1051 1
  2365.         fdPtr->indirect[1] = FS_NIL_INDEX;
  2366. d1059 1
  2367. a1059 1
  2368.          j < FS_INDICES_PER_BLOCK; 
  2369. d1061 1
  2370. a1061 1
  2371.         if (*indexPtr != FS_NIL_INDEX) {
  2372. d1069 1
  2373. a1069 1
  2374.             fdPtr->indirect[1] = FS_NIL_INDEX;
  2375. d1072 3
  2376. a1074 3
  2377.         } else if ( i + j * FS_INDICES_PER_BLOCK > lastBlock) {
  2378.             lastBlock = i + j * FS_INDICES_PER_BLOCK;
  2379.             fdPtr->lastByte += FS_BLOCK_SIZE * FS_INDICES_PER_BLOCK;
  2380. d1083 1
  2381. a1083 1
  2382.         AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS + 1,
  2383. d1087 1
  2384. a1087 1
  2385.          j < FS_INDICES_PER_BLOCK && i <= lastBlock; 
  2386. d1089 1
  2387. a1089 1
  2388.         if (*indexPtr == FS_NIL_INDEX) {
  2389. d1097 1
  2390. a1097 1
  2391.             AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS + 1,
  2392. d1100 1
  2393. a1100 1
  2394.         i += FS_INDICES_PER_BLOCK;
  2395. d1117 1
  2396. a1117 1
  2397.         AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS + 1,
  2398. d1140 1
  2399. a1140 1
  2400.         AddToCopyList(FD, fdPtr, fdNum, 0, FS_NUM_DIRECT_BLOCKS + 1,
  2401. d1143 1
  2402. a1143 1
  2403.         fdPtr->indirect[1] = FS_NIL_INDEX;
  2404. d1204 1
  2405. a1204 1
  2406.     register FsFileDescriptor    *fdPtr;      /* Actual file descriptor. */
  2407. d1210 1
  2408. a1210 1
  2409.     FsDomainHeader    *domainPtr;      /* Domain to read from. */
  2410. d1275 2
  2411. a1276 2
  2412.     *fileBlockNumPtr += FS_INDICES_PER_BLOCK;
  2413.     *blockNumPtr = FS_NIL_INDEX;
  2414. d1289 1
  2415. a1289 1
  2416.      i < FS_INDICES_PER_BLOCK; 
  2417. d1291 1
  2418. a1291 1
  2419.     if (*indexPtr != FS_NIL_INDEX) {
  2420. d1302 2
  2421. a1303 2
  2422.             *fileBlockNumPtr += FS_INDICES_PER_BLOCK;
  2423.             *blockNumPtr = FS_NIL_INDEX;
  2424. d1319 1
  2425. a1319 1
  2426.     if (zeroCount == FS_INDICES_PER_BLOCK) {
  2427. d1325 2
  2428. a1326 2
  2429.     *fileBlockNumPtr += FS_INDICES_PER_BLOCK;
  2430.     *blockNumPtr = FS_NIL_INDEX;
  2431. d1339 1
  2432. a1339 1
  2433.      i < FS_INDICES_PER_BLOCK && *fileBlockNumPtr <= lastBlock; 
  2434. d1342 1
  2435. a1342 1
  2436.      if (*indexPtr == FS_NIL_INDEX) {
  2437. d1378 1
  2438. a1378 1
  2439.         *indexPtr = FS_NIL_INDEX;
  2440. d1420 1
  2441. a1420 1
  2442.     register FsDomainHeader *domainPtr;    /* Domain to allocate the file 
  2443. d1518 1
  2444. a1518 1
  2445.     register FsDomainHeader     *domainPtr;    /* Domain to allocate the file 
  2446. d1530 1
  2447. a1530 1
  2448.     FsFileDescriptor    *fdPtr = NULL;
  2449. d1532 1
  2450. a1532 1
  2451.     static int         block[FS_INDICES_PER_BLOCK];
  2452. d1636 2
  2453. a1637 2
  2454.     FsFileDescriptor    *fdPtr;            /* Ptr at fd of file. */
  2455.     FsDomainHeader    *domainPtr;           /* Ptr at domain info */
  2456. d1651 1
  2457. a1651 1
  2458.     if (blockNum != FS_NIL_INDEX) { 
  2459. d1686 1
  2460. a1686 1
  2461.          i < FS_INDICES_PER_BLOCK; 
  2462. d1689 1
  2463. a1689 1
  2464.          if (*indBlock != FS_NIL_INDEX || 
  2465. d1705 2
  2466. a1706 2
  2467.     } else if (blockNum == FS_NIL_INDEX) {
  2468.     FsDirEntry *entryPtr;
  2469. d1711 3
  2470. a1713 3
  2471.     for (entryPtr = (FsDirEntry *)block, i = 0; 
  2472.          i < fragments * FS_FRAGMENT_SIZE  / FS_DIR_BLOCK_SIZE;
  2473.          i++,entryPtr=(FsDirEntry *)((int)entryPtr + FS_DIR_BLOCK_SIZE)) {
  2474. d1715 1
  2475. a1715 1
  2476.          entryPtr->recordLength = FS_DIR_BLOCK_SIZE;
  2477. @
  2478.  
  2479.  
  2480. 1.28
  2481. log
  2482. @sets file size to 0 if size is negative, then counts blocks to find real 
  2483. size
  2484. @
  2485. text
  2486. @d17 1
  2487. a17 1
  2488. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.27 89/06/21 23:55:49 jhh Exp $ SPRITE (Berkeley)";
  2489. d40 1
  2490. d56 1
  2491. a56 1
  2492. int patchHeader = 0;
  2493. d94 1
  2494. a94 1
  2495.     {OPT_TRUE, "hostID", (Address)&patchHeader,
  2496. d231 3
  2497. d399 2
  2498. a400 14
  2499.     /*
  2500.      * Determine where the disk is located so we can set the
  2501.      * spriteID in the header correctly.  If the disk device is generic
  2502.      * we use our own hostID, otherwise use the hostID specified
  2503.      * by the device file.
  2504.      */
  2505.     fstat(firstPartFID, &attrs);
  2506.     if (attrs.st_devServerID == FS_LOCALHOST_ID) {
  2507.         char    hostName[100];
  2508.         Host_Entry    *hostEntryPtr;
  2509.  
  2510.         gethostname(hostName, 100);
  2511.         hostEntryPtr = Host_ByName(hostName);
  2512.         spriteID = hostEntryPtr->id;
  2513. d402 12
  2514. a413 1
  2515.         spriteID = attrs.st_devServerID;
  2516. d425 1
  2517. a425 1
  2518.         patchHeader = 0;
  2519. @
  2520.  
  2521.  
  2522. 1.27
  2523. log
  2524. @Various bug fixes
  2525. @
  2526. text
  2527. @d17 1
  2528. a17 1
  2529. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fscheck.c,v 1.26 89/02/28 12:21:48 jhh Exp $ SPRITE (Berkeley)";
  2530. d857 12
  2531. d871 1
  2532. d889 2
  2533. @
  2534.  
  2535.  
  2536. 1.26
  2537. log
  2538. @Converted to new C library, added lots of new functionality
  2539. @
  2540. text
  2541. @d17 1
  2542. a17 1
  2543. static char rcsid[] = "$Header: fscheck.c,v 1.24 88/09/20 15:13:32 nelson Exp $ SPRITE (Berkeley)";
  2544. d70 3
  2545. d110 8
  2546. a117 1
  2547.     "Number of blocks to read at a time."},};
  2548. d130 1
  2549. d163 1
  2550. d166 5
  2551. a170 2
  2552.     (void)Opt_Parse(argc, argv, optionArray, numOptions, 0);
  2553.  
  2554. d198 1
  2555. d206 3
  2556. a208 1
  2557.     Output(stderr,"***** Fscheck *****\n%s",timeString);
  2558. d263 3
  2559. d367 1
  2560. d460 1
  2561. a460 1
  2562.     if (!silent) {
  2563. a463 7
  2564.     if (!silent) {
  2565.     if (status) {
  2566.         Output(stderr, "Looks like the disk wasn't synced.\n");
  2567.     } else {
  2568.         Output(stderr, "Looks like the disk was synced.\n");
  2569.     }
  2570.     }
  2571. d470 1
  2572. a470 1
  2573.     if (!silent) {
  2574. d655 1
  2575. a655 1
  2576.     if (!verbose && fdBitmapError) {
  2577. d676 1
  2578. a676 1
  2579.     if (!silent) {
  2580. d698 1
  2581. a698 1
  2582.     if (!silent) {
  2583. d712 1
  2584. a712 1
  2585.     if (!silent) {
  2586. d715 14
  2587. d737 1
  2588. a737 1
  2589.         if (verbose) {
  2590. d746 1
  2591. a746 1
  2592.         if (verbose) {
  2593. d756 1
  2594. a756 1
  2595.     if (!verbose && bitmapError) {
  2596. d769 10
  2597. d783 1
  2598. a783 1
  2599.     if (!silent) {
  2600. d1219 1
  2601. d1268 1
  2602. d1274 4
  2603. d1301 17
  2604. d1559 3
  2605. d1650 1
  2606. a1650 1
  2607.     return;
  2608. d1715 1
  2609. a1715 1
  2610.     if (debug) {
  2611. @
  2612.  
  2613.  
  2614. 1.25
  2615. log
  2616. @Converted over to new C library but not fully tested yet.
  2617. @
  2618. text
  2619. @d5 9
  2620. a13 3
  2621.  *
  2622.  * Copyright (C) 1986 Regents of the University of California
  2623.  * All rights reserved.
  2624. d17 1
  2625. a17 1
  2626. static char rcsid[] = "$Header: checkFS.c,v 1.24 88/09/20 15:13:32 nelson Exp $ SPRITE (Berkeley)";
  2627. d34 1
  2628. d37 3
  2629. d43 1
  2630. a43 1
  2631.  * fscheck -D rsd0 -P b
  2632. d53 1
  2633. d63 7
  2634. d72 1
  2635. a72 1
  2636.     {OPT_STRING, "D", (Address)&deviceName,
  2637. d74 1
  2638. a74 1
  2639.     {OPT_STRING, "P", (Address)&partName,
  2640. d76 1
  2641. a76 1
  2642.     {OPT_STRING, "d", (Address)&devDirectory,
  2643. d78 1
  2644. a78 1
  2645.     {OPT_STRING, "p", (Address)&firstPartName,
  2646. d80 7
  2647. a86 9
  2648.     {OPT_TRUE, "W", (Address)&writeDisk,
  2649.     "Write disk (0)"},
  2650.     {OPT_TRUE, "S", (Address)&silent,
  2651.     "Don't say anything unless there's a problem (0)"},
  2652.     {OPT_TRUE, "V", (Address)&verbose,
  2653.     "Output information about differences in bitmaps (0)"},
  2654.     {OPT_TRUE, "r", (Address)&recoveryCheck,
  2655.      "The domain wasn't synced, increment all version numbers for recovery."},
  2656.     {OPT_TRUE, "R", (Address)&patchRoot,
  2657. d88 1
  2658. a88 1
  2659.     {OPT_TRUE, "c", (Address)&clearDomainNumber,
  2660. d90 1
  2661. a90 1
  2662.     {OPT_TRUE, "H", (Address)&patchHeader,
  2663. d92 1
  2664. a92 1
  2665.     {OPT_TRUE, "b", (Address)&badBlockInit,
  2666. d94 14
  2667. a107 1
  2668. };
  2669. a114 1
  2670. static int    incVersionNumbers;
  2671. a132 3
  2672.  *    checkFS exits with status == 0 if the disk was completly clean
  2673.  *        with status == 1 if correctable errors were found
  2674.  *        with status == -1 if really bad errors were found.
  2675. a143 1
  2676.     int        partFID;
  2677. d147 5
  2678. d153 1
  2679. d156 39
  2680. d196 2
  2681. a197 2
  2682.     fprintf(stderr, "Specify device name with -D option\n");
  2683.     exit(EXIT_HARD_ERR);
  2684. d200 2
  2685. a201 2
  2686.     fprintf(stderr, "Specify partition with -P option\n");
  2687.     exit(EXIT_HARD_ERR);
  2688. d203 9
  2689. a211 1
  2690.  
  2691. d225 2
  2692. a226 2
  2693.     perror("checkFS: Can't open first parition");
  2694.     exit(EXIT_HARD_ERR);
  2695. d230 2
  2696. a231 2
  2697.     perror("checkFS: Can't open partition to check ");
  2698.     exit(EXIT_HARD_ERR);
  2699. d236 3
  2700. a238 3
  2701.     fprintf(stderr,
  2702.          "checkFS: Can't determine partition index from the partition name\n");
  2703.     exit(EXIT_HARD_ERR);
  2704. d240 5
  2705. d247 3
  2706. d253 4
  2707. a256 3
  2708.     exit(EXIT_SOFT_ERR);
  2709.     } else {
  2710.     exit(EXIT_OK);
  2711. d258 1
  2712. d267 1
  2713. a267 1
  2714. static unsigned char bitmasks[BITS_PER_BYTE] = {
  2715. d286 2
  2716. a287 2
  2717. static int    num1KBlocks;
  2718. static int    bytesPerCylinder;
  2719. d289 2
  2720. d292 1
  2721. a292 1
  2722. List_Links    relocListHdr;
  2723. a293 16
  2724. /*
  2725.  * Macro to get a pointer into the bit map for a particular block.
  2726.   */
  2727. #define BlockToCylinder(domainPtr, blockNum) \
  2728.     (blockNum) / (domainPtr)->geometry.blocksPerCylinder
  2729.  
  2730. #define GetBitmapPtr(domainPtr, bitmapPtr, blockNum) \
  2731.   &((bitmapPtr)[BlockToCylinder(domainPtr, blockNum) * \
  2732.   bytesPerCylinder + (blockNum) % (domainPtr)->geometry.blocksPerCylinder / 2])
  2733.  
  2734. /*
  2735.  * Number of file descriptors in a sector, if we have to go through
  2736.  * the sectors individually.
  2737.  */
  2738. #define FILE_DESC_PER_SECTOR (FS_FILE_DESC_PER_BLOCK / DISK_SECTORS_PER_BLOCK)
  2739.  
  2740. d306 1
  2741. a306 1
  2742.  *    None.
  2743. a318 1
  2744.     register    FsDomainHeader  *domainPtr;
  2745. d321 1
  2746. a321 1
  2747.     int                i, j;
  2748. d323 1
  2749. a323 1
  2750.     char            block[FS_BLOCK_SIZE];
  2751. a328 1
  2752.     RelocListElement        *relocElemPtr;
  2753. d333 11
  2754. d352 2
  2755. a353 2
  2756.     fprintf(stderr, "CheckFilesystem: Could not read basic disk info\n");
  2757.     exit(EXIT_HARD_ERR);
  2758. d357 1
  2759. a357 2
  2760.  
  2761.     domainPtr = (FsDomainHeader *) malloc(diskInfoPtr->numDomainSectors *
  2762. d359 5
  2763. d391 4
  2764. a394 2
  2765.         fprintf(stderr, "Setting hostID in disk header to 0x%x\n",
  2766.             spriteID);
  2767. d397 3
  2768. d402 3
  2769. a405 1
  2770.  
  2771. d411 6
  2772. a416 2
  2773.     newCylBitmapPtr =
  2774.       (unsigned char *)malloc(domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  2775. d421 5
  2776. a425 1
  2777.     descInfoPtr = (FdInfo *)malloc(domainPtr->numFileDesc * sizeof(FdInfo));
  2778. d433 1
  2779. d438 9
  2780. a446 5
  2781.     if (recoveryCheck) {
  2782.     fprintf(stderr, "Performing recovery check\n");
  2783.     incVersionNumbers = RecoveryCheck(partFID, diskInfoPtr);
  2784.     if (incVersionNumbers) {
  2785.         fprintf(stderr, "Disk not safely synced.  Will increment all version numbers.\n");
  2786. a447 2
  2787.     } else {
  2788.     incVersionNumbers = 0;
  2789. d456 1
  2790. a456 1
  2791.     fprintf(stderr, "Checking file descriptors:\n");
  2792. d462 5
  2793. a466 1
  2794.  
  2795. d468 7
  2796. a474 19
  2797.      i < (domainPtr->numFileDesc + FS_FILE_DESC_PER_BLOCK - 1) / 
  2798.         FS_FILE_DESC_PER_BLOCK;
  2799.      i++) {
  2800.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->fileDescOffset + i,
  2801.                 1, (Address) block) < 0) {
  2802.         /*
  2803.          * Hit a disk error reading the block.  Read it a sector
  2804.          * at a time and try to salvage what we can.
  2805.          */
  2806.         perror("CheckFilesystem: BlockRead: Read failed");
  2807.         validMask = Disk_BadBlockRead(partFID, domainPtr,
  2808.                       domainPtr->fileDescOffset + i,
  2809.                       (Address) block);
  2810.         SetBadDescBitmap(domainPtr, fdNum, &tFdBitmapPtr);
  2811.         salvage = 1;
  2812.     } else {
  2813.         CheckFDBitmap(domainPtr, fdNum, block, &tFdBitmapPtr);
  2814.         salvage = 0;
  2815.         valid = 1;
  2816. d476 25
  2817. a500 4
  2818.     for (sector = 0; sector < DISK_SECTORS_PER_BLOCK; sector++) {
  2819.         if (salvage) {
  2820.         valid = (validMask & (1 << sector)) != 0;
  2821.         numBadDesc++;
  2822. d502 42
  2823. a543 11
  2824.         for (j = 0; 
  2825.          j < FILE_DESC_PER_SECTOR && fdNum < domainPtr->numFileDesc;
  2826.          j++, fdNum++, tDescInfoPtr++, fdPtr++) {
  2827.  
  2828.         int    modified = 0;
  2829.         fdPtr = (FsFileDescriptor *)
  2830.             &block[(j + (FILE_DESC_PER_SECTOR * sector)) *
  2831.                    FS_MAX_FILE_DESC_SIZE];
  2832.         if (valid) {
  2833.             if (fdPtr->fileType == FS_DIRECTORY) {
  2834.             tDescInfoPtr->flags |= IS_A_DIRECTORY;
  2835. d545 21
  2836. a565 3
  2837.             if (fdPtr->flags & FS_FD_ALLOC) {
  2838.             if (incVersionNumbers && fdPtr->fileType != FS_DEVICE) {
  2839.                 fdPtr->version++;
  2840. d567 3
  2841. a569 5
  2842.             tDescInfoPtr->flags |= FD_ALLOCATED;
  2843.             tDescInfoPtr->origLinkCount = fdPtr->numLinks;
  2844.  
  2845.             CheckBlocks(partFID, domainPtr, fdNum, fdPtr,
  2846.                     newCylBitmapPtr, &modified);
  2847. d571 7
  2848. a577 4
  2849.         }
  2850.         if (salvage) {
  2851.             if (valid && (fdPtr->flags & FS_FD_ALLOC)) {
  2852.             RelocListElement    *relocElemPtr;
  2853. d579 13
  2854. a591 9
  2855.             tDescInfoPtr->flags |= FD_RELOCATE;
  2856.             relocElemPtr = (RelocListElement *)
  2857.                 malloc(sizeof(RelocListElement));
  2858.             relocElemPtr->origFdNum = fdNum;
  2859.             relocElemPtr->newFdNum = -1;
  2860.             bcopy((Address)fdPtr, (Address)&relocElemPtr->fd, 
  2861.                   sizeof(FsFileDescriptor));
  2862.             List_Insert((List_Links *)relocElemPtr,
  2863.                     LIST_ATREAR(relocList));
  2864. d593 11
  2865. a603 2
  2866.             if (!valid) {
  2867.             tDescInfoPtr->flags |= FD_UNREADABLE;
  2868. d605 3
  2869. a607 19
  2870.         }
  2871.         /*
  2872.          * Essentially the same code is used to zero out an unuseable
  2873.          * descriptor and to initialize the bad block descriptor.
  2874.          */
  2875.         if ((badBlockInit && fdNum == FS_BAD_BLOCK_FILE_NUMBER) ||
  2876.                 salvage) {
  2877.             int    index;
  2878.  
  2879.             fdPtr->flags = valid ? FS_FD_ALLOC : FS_FD_FREE;
  2880.             fdPtr->firstByte = -1;
  2881.             fdPtr->lastByte = -1;
  2882.             fdPtr->numKbytes = 0;
  2883.             fdPtr->fileType = FS_FILE;
  2884.             fdPtr->uid = 0;
  2885.             fdPtr->gid = 0;
  2886.             fdPtr->numLinks = 0;
  2887.             for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
  2888.             fdPtr->direct[index] = FS_NIL_INDEX;
  2889. d609 4
  2890. a612 2
  2891.             for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
  2892.             fdPtr->indirect[index] = FS_NIL_INDEX;
  2893. d614 3
  2894. a616 1
  2895.             modified = 1;
  2896. a617 11
  2897.         if (modified) {
  2898.             ModListElement    *modElemPtr;
  2899.  
  2900.             tDescInfoPtr->flags |= ON_MOD_LIST;
  2901.             modElemPtr =
  2902.                 (ModListElement *)malloc(sizeof(ModListElement));
  2903.             modElemPtr->fdNum = fdNum;
  2904.             bcopy((Address)fdPtr, (Address)&modElemPtr->fd, 
  2905.                   sizeof(FsFileDescriptor));
  2906.             List_Insert((List_Links *)modElemPtr, LIST_ATREAR(modList));
  2907.         }
  2908. d619 9
  2909. a627 6
  2910.         if (incVersionNumbers && writeDisk) {
  2911.         if (Disk_BlockWrite(partFID, domainPtr,
  2912.                     domainPtr->fileDescOffset + i,
  2913.                     1, (Address) block) < 0) {
  2914.             perror("CheckFileSystem: FD write failed");
  2915.             exit(EXIT_HARD_ERR);
  2916. d631 8
  2917. a639 1
  2918.  
  2919. d641 1
  2920. a641 1
  2921.     fprintf(stderr, "Found error in file descriptor bitmap\n");
  2922. d644 1
  2923. d646 49
  2924. d698 1
  2925. a698 1
  2926.     fprintf(stderr, "\nComparing old and new data block bit maps:\n");
  2927. d709 1
  2928. a709 1
  2929.             fprintf(stderr,"Block %d: old %x new %x.\n",
  2930. d711 1
  2931. a711 1
  2932.             *oldPtr & 0xf0, *newPtr & 0xf0);
  2933. d718 1
  2934. a718 1
  2935.             fprintf(stderr,"Block %d: old %x new %x.\n",
  2936. d728 1
  2937. a728 1
  2938.     fprintf(stderr, "Found error in data block bitmap\n");
  2939. a732 22
  2940.      * We now know which descriptors, if any, need to be relocated.  Allocate
  2941.      * new descriptors to hold the information.
  2942.      */
  2943.  
  2944.     if (!(List_IsEmpty(relocList))) {
  2945.     LIST_FORALL(relocList, (List_Links *)relocElemPtr) {
  2946.         RelocateFD(domainPtr, descInfoPtr, relocElemPtr);
  2947.     }
  2948.     }
  2949.     
  2950.  
  2951.     /*
  2952.      * Go through the file system starting at the root and perform a 
  2953.      * consistency check.
  2954.      */
  2955.     if (!silent) {
  2956.     fprintf(stderr, "\nTraversing directory tree:\n\n");
  2957.     }
  2958.  
  2959.     CheckDirTree(partFID, domainPtr, descInfoPtr);
  2960.  
  2961.     /*
  2962. d735 1
  2963. a735 1
  2964.     fprintf(stdout, 
  2965. d745 1
  2966. a745 1
  2967.     fprintf(stderr, "Writing disk\n");
  2968. d773 1
  2969. a773 1
  2970.  * ReadDomainHeader --
  2971. d775 1
  2972. a775 1
  2973.  *    Read the domain header off the disk.
  2974. a776 2
  2975.  * Results:
  2976.  *    None.
  2977. a777 27
  2978.  * Side effects:
  2979.  *    Fill in the domain header.
  2980.  *
  2981.  *----------------------------------------------------------------------
  2982.  */
  2983. void
  2984. ReadDomainHeader(partFID, diskInfoPtr, domainPtr)
  2985.     int            partFID;    /* Handle on raw disk */
  2986.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  2987.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  2988.                      * fill in */
  2989. {
  2990.     if (Disk_SectorRead(partFID, diskInfoPtr->domainSector,
  2991.            diskInfoPtr->numDomainSectors, (Address)domainPtr) < 0) {
  2992.     perror("ReadDomainHeader: Read failed");
  2993.     exit(EXIT_HARD_ERR);
  2994.     }
  2995. }
  2996.  
  2997.  
  2998. /*
  2999.  *----------------------------------------------------------------------
  3000.  *
  3001.  * WriteDomainHeader --
  3002.  *
  3003.  *    Read the domain header off the disk.
  3004.  *
  3005. d782 1
  3006. a782 1
  3007.  *    Fill in the domain header.
  3008. d787 2
  3009. a788 412
  3010. WriteDomainHeader(partFID, diskInfoPtr, domainPtr)
  3011.     int            partFID;    /* Handle on raw disk */
  3012.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  3013.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  3014.                      * fill in */
  3015. {
  3016.     if (Disk_SectorWrite(partFID, diskInfoPtr->domainSector,
  3017.             diskInfoPtr->numDomainSectors, (Address)domainPtr) < 0) {
  3018.     perror("WriteDomainHeader: Write failed");
  3019.     exit(EXIT_HARD_ERR);
  3020.     }
  3021. }
  3022.  
  3023.  
  3024. /*
  3025.  *----------------------------------------------------------------------
  3026.  *
  3027. * ReadFileDescBitmap --
  3028.  *
  3029.  *    Read in the file descriptor bitmap.
  3030.  *
  3031.  * Results:
  3032.  *    A pointer to the file descriptor bit map.
  3033.  *
  3034.  * Side effects:
  3035.  *    Memory allocated for the bit map.
  3036.  *
  3037.  *----------------------------------------------------------------------
  3038.  */
  3039. unsigned char *
  3040. ReadFileDescBitmap(partFID, domainPtr)
  3041.     register FsDomainHeader *domainPtr;    /* Ptr to domain to read bitmap for. */
  3042. {
  3043.     register unsigned char *bitmap;
  3044.  
  3045.     /*
  3046.      * Allocate the bitmap.
  3047.      */
  3048.     bitmap =(unsigned char *)malloc(domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  3049.  
  3050.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
  3051.           domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  3052.     perror("ReadFileDescBitmap: Read failed");
  3053.     exit(EXIT_HARD_ERR);
  3054.     }
  3055.     return(bitmap);
  3056. }
  3057.  
  3058.  
  3059. /*
  3060.  *----------------------------------------------------------------------
  3061.  *
  3062.  * WriteFileDescBitmap --
  3063.  *
  3064.  *    Write out the file descriptor bitmap.
  3065.  *
  3066.  * Results:
  3067.  *    None.
  3068.  *
  3069.  * Side effects:
  3070.  *    None.
  3071.  *
  3072.  *----------------------------------------------------------------------
  3073.  */
  3074. void
  3075. WriteFileDescBitmap(partFID, domainPtr, bitmap)
  3076.     int                partFID;    /* Raw handle on disk. */
  3077.     register FsDomainHeader     *domainPtr;    /* Domain to write bitmap for.*/
  3078.     register unsigned char     *bitmap;    /* Bitmap to write. */
  3079. {
  3080.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  3081.            domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  3082.     perror("WriteFileDescBitmap: Write failed");
  3083.     exit(EXIT_HARD_ERR);
  3084.     }
  3085. }
  3086.  
  3087.  
  3088. /*
  3089.  *----------------------------------------------------------------------
  3090.  *
  3091.  * ReadBitmap --
  3092.  *
  3093.  *    Read the bitmap off disk.
  3094.  *
  3095.  * Results:
  3096.  *    A pointer to the bitmap.
  3097.  *
  3098.  * Side effects:
  3099.  *    Memory allocated for the bit map.
  3100.  *
  3101.  *----------------------------------------------------------------------
  3102.  */
  3103. unsigned char *
  3104. ReadBitmap(partFID, domainPtr)
  3105.     int                partFID;    /* Raw disk handle. */
  3106.     register FsDomainHeader    *domainPtr;    /* Domain to read. */
  3107. {
  3108.     unsigned char *bitmap;
  3109.  
  3110.     bitmap = (unsigned char *)malloc(domainPtr->bitmapBlocks*FS_BLOCK_SIZE);
  3111.  
  3112.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
  3113.           domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  3114.     perror("ReadBitmap: Read failed");
  3115.     exit(EXIT_HARD_ERR);
  3116.     }
  3117.     return(bitmap);
  3118. }
  3119.  
  3120.  
  3121. /*
  3122.  *----------------------------------------------------------------------
  3123.  *
  3124.  * WriteBitmap --
  3125.  *
  3126.  *    Write the bitmap to disk.
  3127.  *
  3128.  * Results:
  3129.  *    None.
  3130.  *
  3131.  * Side effects:
  3132.  *    None.
  3133.  *
  3134.  *----------------------------------------------------------------------
  3135.  */
  3136. void
  3137. WriteBitmap(partFID, domainPtr, bitmap)
  3138.     int                partFID;    /* Raw handle for disk. */
  3139.     register FsDomainHeader    *domainPtr;    /* Domain to write. */
  3140.     unsigned char        *bitmap;    /* Bitmap to write. */
  3141. {
  3142.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  3143.            domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  3144.     perror("WriteBitmap: Write failed");
  3145.     exit(EXIT_HARD_ERR);
  3146.     }
  3147. }
  3148.  
  3149.  
  3150. /*
  3151.  *----------------------------------------------------------------------
  3152.  *
  3153.  * WriteFileDesc --
  3154.  *
  3155.  *    Write the file descriptors to disk.
  3156.  *
  3157.  * Results:
  3158.  *    None.
  3159.  *
  3160.  * Side effects:
  3161.  *    File descriptors on the modified list are all written to disk.
  3162.  *
  3163.  *----------------------------------------------------------------------
  3164.  */
  3165. void
  3166. WriteFileDesc(partFID, domainPtr, listPtr, descInfoPtr)
  3167.     int             partFID;    /* Raw handle for disk. */
  3168.     register FsDomainHeader     *domainPtr;    /* Domain to write to. */
  3169.     List_Links            *listPtr;    /* Pointer to list of modified
  3170.                          * file descriptors to write
  3171.                          * out. */
  3172.     FdInfo            *descInfoPtr;    /* Pointer to info about all
  3173.                          * of the descriptors. */
  3174.                     
  3175. {
  3176.     char        block[FS_BLOCK_SIZE];
  3177.     int            blockNum;
  3178.     int            offset;
  3179.     ModListElement    *modElemPtr;
  3180.     int            badBlock;
  3181.  
  3182.     LIST_FORALL(listPtr, (List_Links *)modElemPtr) {
  3183.     badBlock = 0;
  3184.     blockNum = domainPtr->fileDescOffset + 
  3185.             modElemPtr->fdNum / FS_FILE_DESC_PER_BLOCK;
  3186.     offset = (modElemPtr->fdNum & (FS_FILE_DESC_PER_BLOCK - 1)) *
  3187.             FS_MAX_FILE_DESC_SIZE;
  3188.     /*
  3189.      * Try to read the whole block at once unless we already know it's
  3190.      * bad.  Read it a sector at a time if we hit an error earlier
  3191.      * or if we get one now.
  3192.      */
  3193.     if ((descInfoPtr[modElemPtr->fdNum].flags &
  3194.          (FD_RELOCATE|FD_UNREADABLE)) == 0) {
  3195.         if (Disk_BlockRead(partFID, domainPtr, blockNum, 1,
  3196.                    (Address) block) < 0) {
  3197.         perror("WriteFileDesc: Warning: read failed");
  3198.         badBlock = 1;
  3199.         }
  3200.     } else {
  3201.         badBlock = 1;
  3202.     }
  3203.     if (badBlock) {
  3204.         (void) Disk_BadBlockRead(partFID, domainPtr, blockNum,
  3205.                      (Address) block);
  3206.     }
  3207.     bcopy((Address) &modElemPtr->fd, (Address) &block[offset],
  3208.           sizeof(FsFileDescriptor));
  3209.     if (Disk_BlockWrite(partFID, domainPtr, blockNum, 1,
  3210.                (Address) block) < 0) {
  3211.         perror("WriteFileDesc: Write failed");
  3212.         exit(EXIT_HARD_ERR);
  3213.     }
  3214.     }
  3215. }
  3216.  
  3217.  
  3218. /*
  3219.  *----------------------------------------------------------------------
  3220.  *
  3221.  * WriteSummaryInfo --
  3222.  *
  3223.  *    Update summary information on disk.
  3224.  *
  3225.  * Results:
  3226.  *    None.
  3227.  *
  3228.  * Side effects:
  3229.  *    None.
  3230.  *
  3231.  *----------------------------------------------------------------------
  3232.  */
  3233. void
  3234. WriteSummaryInfo(partFID, diskInfoPtr, domainPtr, numKblocks, numFiles)
  3235.     int            partFID;    /* Handle on raw disk */
  3236.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  3237.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  3238.                      * fill in */
  3239.     int            numKblocks;    /* Number of 1 Kbyte blocks. */
  3240.     int            numFiles;    /* Number of files. */
  3241. {
  3242.     char        buffer[DEV_BYTES_PER_SECTOR];
  3243.     FsSummaryInfo    *summaryInfoPtr;
  3244.  
  3245.     if (Disk_SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  3246.     perror("WriteSummaryInfo: Read failed");
  3247.     exit(EXIT_HARD_ERR);
  3248.     }
  3249.     summaryInfoPtr = (FsSummaryInfo *) buffer;
  3250.     summaryInfoPtr->numFreeFileDesc = domainPtr->numFileDesc - numFiles -
  3251.         numBadDesc;
  3252.     summaryInfoPtr->numFreeKbytes = 
  3253.         domainPtr->dataBlocks * FS_FRAGMENTS_PER_BLOCK - numKblocks;
  3254.     if (clearDomainNumber) {
  3255.     summaryInfoPtr->domainNumber = -1;
  3256.     }
  3257.     summaryInfoPtr->flags = 0;
  3258.     if (Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  3259.     perror("WriteSummaryInfo: Write failed");
  3260.     exit(EXIT_HARD_ERR);
  3261.     }
  3262.  
  3263. }
  3264.  
  3265.  
  3266. /*
  3267.  *----------------------------------------------------------------------
  3268.  *
  3269.  * RecoveryCheck --
  3270.  *
  3271.  *    See if the disk was successfully synced.
  3272.  *
  3273.  * Results:
  3274.  *    Return 1 if the disk not safely synced.
  3275.  *
  3276.  * Side effects:
  3277.  *    None.
  3278.  *
  3279.  *----------------------------------------------------------------------
  3280.  */
  3281. int
  3282. RecoveryCheck(partFID, diskInfoPtr)
  3283.     int            partFID;    /* Handle on raw disk */
  3284.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  3285. {
  3286.     char            buffer[DEV_BYTES_PER_SECTOR];
  3287.     FsSummaryInfo        *summaryInfoPtr;
  3288.  
  3289.     if (Disk_SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  3290.     perror("RecoveryCheck: Summary sector read failed");
  3291.     exit(EXIT_HARD_ERR);
  3292.     }
  3293.     summaryInfoPtr = (FsSummaryInfo *)buffer;
  3294.     return(summaryInfoPtr->flags & FS_DOMAIN_NOT_SAFE);
  3295. }
  3296.  
  3297.  
  3298. /*
  3299.  *----------------------------------------------------------------------
  3300.  *
  3301.  * CheckFDBitmap --
  3302.  *
  3303.  *    Scan through the file descriptors and determine if all file 
  3304.  *    descriptors marked as allocated and free in the bit map are
  3305.  *    really that way.
  3306.  *
  3307.  * Results:
  3308.  *    None.
  3309.  *
  3310.  * Side effects:
  3311.  *    None.
  3312.  *
  3313.  *----------------------------------------------------------------------
  3314.  */
  3315.  
  3316. void
  3317. CheckFDBitmap(domainPtr, fdNum, block, bitmapPtrPtr)
  3318.     register    FsDomainHeader     *domainPtr;        /* Domain to check. */
  3319.     int                 fdNum;            /* File descriptor to
  3320.                              * check. */
  3321.     Address             block;            /* Disk block that
  3322.                              * FD is in. */
  3323.     register    unsigned char      **bitmapPtrPtr;    /* Ptr to FD bitmap
  3324.                              * entry for fdNum. */
  3325. {
  3326.     int                i, j;
  3327.     register unsigned char     *bitmaskPtr;
  3328.     int                   allocated;
  3329.     FsFileDescriptor        *fdPtr;
  3330.  
  3331.     for (i = 0; 
  3332.      i < FS_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  3333.         fdNum < domainPtr->numFileDesc;
  3334.      i++, (*bitmapPtrPtr)++){
  3335.     for (j = 0, bitmaskPtr = bitmasks; 
  3336.          j < BITS_PER_BYTE && fdNum < domainPtr->numFileDesc; 
  3337.          j++, fdNum++, bitmaskPtr++) {
  3338.  
  3339.         fdPtr = (FsFileDescriptor *)&block[(i * BITS_PER_BYTE + j) * FS_MAX_FILE_DESC_SIZE];
  3340.         allocated = **bitmapPtrPtr & *bitmaskPtr;
  3341.         if (allocated && (fdPtr->flags & FS_FD_FREE)) {
  3342.         if (verbose) {
  3343.             fprintf(stderr,
  3344.        "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n",
  3345.                    fdNum);
  3346.         }
  3347.         foundError = 1;
  3348.         fdBitmapError = 1;
  3349.         **bitmapPtrPtr &= ~*bitmaskPtr;
  3350.         } else if (!allocated && !(fdPtr->flags & FS_FD_FREE)) {
  3351.         if (verbose) {
  3352.             fprintf(stderr,
  3353.        "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n",
  3354.                    fdNum);
  3355.         }
  3356.         foundError = 1;
  3357.         fdBitmapError = 1;
  3358.         **bitmapPtrPtr |= *bitmaskPtr;
  3359.         }
  3360.     }
  3361.     }
  3362. }
  3363.  
  3364.  
  3365. /*
  3366.  *----------------------------------------------------------------------
  3367.  *
  3368.  * SetBadDescBitmap --
  3369.  *
  3370.  *    Go through the bitmaps and flag all the bits for this block as
  3371.  *    allocated.
  3372.  *
  3373.  * Results:
  3374.  *    None.
  3375.  *
  3376.  * Side effects:
  3377.  *    None.
  3378.  *
  3379.  *----------------------------------------------------------------------
  3380.  */
  3381. void
  3382. SetBadDescBitmap(domainPtr, fdNum, bitmapPtrPtr)
  3383.     register    FsDomainHeader     *domainPtr;        /* Domain to fix. */
  3384.     int                 fdNum;            /* Bad file desc. */
  3385.     register    unsigned char      **bitmapPtrPtr;    /* Ptr to bitmap entry
  3386.                              * for bad file desc.*/
  3387. {
  3388.     int                i, j;
  3389.     register unsigned char     *bitmaskPtr;
  3390.  
  3391.     for (i = 0; i < FS_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  3392.         fdNum < domainPtr->numFileDesc;
  3393.          i++, (*bitmapPtrPtr)++){
  3394.     for (j = 0, bitmaskPtr = bitmasks; 
  3395.          j < BITS_PER_BYTE && fdNum < domainPtr->numFileDesc; 
  3396.          j++, fdNum++, bitmaskPtr++) {
  3397.  
  3398.          **bitmapPtrPtr |= *bitmaskPtr;
  3399.      }
  3400.     }
  3401. }
  3402.  
  3403.  
  3404. /*
  3405.  *----------------------------------------------------------------------
  3406.  *
  3407.  * CheckBlocks --
  3408.  *
  3409.  *    Scan through the file descriptors and the cylinder bitmap and 
  3410.  *    determine if all blocks marked as allocated are accounted for.
  3411.  *
  3412.  * Results:
  3413.  *    None.
  3414.  *
  3415.  * Side effects:
  3416.  *    None.
  3417.  *
  3418.  *----------------------------------------------------------------------
  3419.  */
  3420. void
  3421. CheckBlocks(partFID, domainPtr, fdNum, fdPtr, newCylBitmapPtr, modifiedPtr)
  3422. d796 3
  3423. a798 3
  3424.     int            *modifiedPtr;        /* TRUE => modified the file
  3425.                          * descriptor. */
  3426. {
  3427. d801 1
  3428. a801 1
  3429.     int             *dblIndirectBlock[FS_INDICES_PER_BLOCK];
  3430. d810 2
  3431. d830 2
  3432. a831 1
  3433.      * First check direct blocks.
  3434. d834 7
  3435. a840 10
  3436.     if (i > lastBlock) {
  3437.         if (fdPtr->direct[i] != FS_NIL_INDEX) {
  3438.         if (verbose || lastErrorFD != fdNum) {
  3439.             fprintf(stderr, 
  3440.             "Extra direct block %d in file %d. Block %d abandoned\n",
  3441.             i, fdNum, fdPtr->direct[i]);
  3442.             lastErrorFD = fdNum;
  3443.         }
  3444.         fdPtr->direct[i] = FS_NIL_INDEX;
  3445.         *modifiedPtr = 1;
  3446. d842 10
  3447. a851 1
  3448.     } else if (fdPtr->direct[i] != FS_NIL_INDEX) {
  3449. d867 3
  3450. a869 3
  3451.             fprintf(stderr,
  3452.     "Fragmented block that is not the last in file %d. Block deleted.\n",
  3453.                     fdNum);
  3454. d884 11
  3455. d897 11
  3456. a907 1
  3457.         *modifiedPtr = 1;
  3458. d910 3
  3459. d916 2
  3460. a917 1
  3461.         fprintf(stderr, "Hole in directory %d.\n", fdNum);
  3462. d920 3
  3463. a922 1
  3464.         goto truncFile;
  3465. a924 13
  3466.     if (i > lastBlock) {
  3467.     if (lastRealBlock != lastBlock) {
  3468.         if (verbose || lastErrorFD != fdNum) {
  3469.         fprintf(stderr, "Missing last block in file %d.\n",
  3470.                    fdNum);
  3471.         lastErrorFD = fdNum;
  3472.         }
  3473.         goto truncFile;
  3474.     } else {
  3475.         goto checkBlockCount;
  3476.     }
  3477.     }
  3478.  
  3479. d929 2
  3480. a930 1
  3481.     if (fdPtr->fileType == FS_DIRECTORY) {
  3482. d932 2
  3483. a933 2
  3484.         fprintf(stderr,
  3485.         "Hole in directory %d because single indirect block is NIL.\n",
  3486. d937 2
  3487. a938 1
  3488.         goto truncFile;
  3489. d943 5
  3490. a947 5
  3491.     status = ProcessIndirectBlock(fdNum, fdPtr, 
  3492.                       &fdPtr->indirect[0],
  3493.                       newCylBitmapPtr, partFID, domainPtr, 
  3494.                       lastBlock, &tBlock, &dirty, 
  3495.                       &lastRealBlock, modifiedPtr, &blockCount);
  3496. d949 7
  3497. d958 2
  3498. a959 2
  3499.         fprintf(stderr, 
  3500.                 "Hole in directory %d in single indirect block\n",
  3501. d963 3
  3502. a965 3
  3503.         goto truncFile;
  3504.     }
  3505.     numBlocks += FS_FRAGMENTS_PER_BLOCK;
  3506. d967 2
  3507. a968 20
  3508.     if (i > lastBlock) {
  3509.     if (lastRealBlock != lastBlock) {
  3510.         if (verbose || lastErrorFD != fdNum) {
  3511.         fprintf(stderr, 
  3512.         "Missing last block in singly indirect block for file %d\n",
  3513.                    fdNum);
  3514.         lastErrorFD = fdNum;
  3515.         }
  3516.         goto truncFile;
  3517.     } else {
  3518.         goto checkBlockCount;
  3519.     }
  3520.     } else if (fdPtr->indirect[1] == FS_NIL_INDEX) {
  3521.     if (verbose || lastErrorFD != fdNum) {
  3522.         fprintf(stderr,
  3523.     "Last block missing in file %d because doubly indirect block is nil\n",
  3524.                fdNum);
  3525.         lastErrorFD = fdNum;
  3526.     }
  3527.     goto truncFile;
  3528. d977 3
  3529. a979 3
  3530.         fprintf(stderr, 
  3531.   "Doubly indirect block on non-block boundary for file %d.  Block deleted.\n",
  3532.               fdNum);
  3533. d985 1
  3534. a985 2
  3535.     status = MarkBitmap(fdNum, 
  3536.         indBlock - domainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK, 
  3537. a989 3
  3538.         /*
  3539.      * FIXME: need to be able to flag this as a bad block on error.
  3540.      */
  3541. d993 4
  3542. a996 2
  3543.         perror("CheckBlocks: Read failed");
  3544.         exit(EXIT_HARD_ERR);
  3545. d998 3
  3546. d1002 28
  3547. d1035 1
  3548. a1035 1
  3549.             fprintf(stderr, 
  3550. d1040 2
  3551. a1041 1
  3552.             goto truncFile;
  3553. d1043 1
  3554. d1047 7
  3555. a1053 7
  3556.         status = ProcessIndirectBlock(fdNum, fdPtr, indexPtr, 
  3557.                       newCylBitmapPtr, 
  3558.                       partFID, domainPtr, lastBlock, 
  3559.                       &tBlock, &dirty, &lastRealBlock,
  3560.                       modifiedPtr, &blockCount);
  3561.         i = tBlock;
  3562.         if (status < 0) {
  3563. d1055 1
  3564. a1055 1
  3565.             fprintf(stderr, 
  3566. d1060 2
  3567. a1061 1
  3568.         goto truncFile;
  3569. a1062 1
  3570.         numBlocks += FS_FRAGMENTS_PER_BLOCK;
  3571. d1064 4
  3572. d1073 2
  3573. a1074 2
  3574.             perror("CheckBlocks: Write failed");
  3575.             exit(EXIT_HARD_ERR);
  3576. d1078 3
  3577. d1082 7
  3578. a1088 2
  3579.     fdPtr->indirect[1] = FS_NIL_INDEX;
  3580.     *modifiedPtr = 1;
  3581. d1102 1
  3582. a1102 1
  3583.     fprintf(stderr,"Truncating file %d to length %d\n", fdNum,
  3584. d1111 1
  3585. a1111 1
  3586.         fprintf(stderr,
  3587. a1119 25
  3588.     /*
  3589.      * Check against extra indirect block pointers.
  3590.      */
  3591.     if (lastRealBlock < FS_NUM_DIRECT_BLOCKS) {
  3592.     j = 0;    /* check all indirect blocks */
  3593.     } else if (lastRealBlock < FS_NUM_DIRECT_BLOCKS + FS_INDICES_PER_BLOCK) {
  3594.     j = 1;    /* check double and triple indirect blocks */
  3595.     } else if (lastRealBlock < FS_NUM_DIRECT_BLOCKS + FS_INDICES_PER_BLOCK +
  3596.                 FS_INDICES_PER_BLOCK * FS_INDICES_PER_BLOCK) {
  3597.     j = 2;    /* check triple indirect block */
  3598.     } else {
  3599.     j = 3;
  3600.     }
  3601.     for (i=j ; i<3 ; i++) {
  3602.     if (fdPtr->indirect[i] != FS_NIL_INDEX) {
  3603.         if (verbose || lastErrorFD != fdNum) {
  3604.         fprintf(stderr, 
  3605.         "Extra indirect block %d in file %d. Block %d abandoned\n",
  3606.                    i, fdNum, fdPtr->indirect[i]);
  3607.         lastErrorFD = fdNum;
  3608.         }
  3609.         fdPtr->indirect[i] = FS_NIL_INDEX;
  3610.         *modifiedPtr = 1;
  3611.     }
  3612.     }
  3613. a1120 1
  3614.  
  3615. d1131 2
  3616. a1132 1
  3617.  *    -1 if found a hole in an indirect block for a directory and
  3618. d1141 4
  3619. a1144 3
  3620. ProcessIndirectBlock(fdNum, fdPtr, blockNumPtr, newCylBitmapPtr, partFID,
  3621.             domainPtr, lastBlock, fileBlockNumPtr, dirtyPtr,
  3622.             lastRealBlockPtr, modifiedPtr, blockCountPtr)
  3623. d1165 7
  3624. d1173 1
  3625. a1173 1
  3626.     char        indirectBlock[FS_BLOCK_SIZE];
  3627. d1178 2
  3628. d1181 2
  3629. d1185 1
  3630. a1185 1
  3631.         fprintf(stderr, 
  3632. d1193 1
  3633. a1193 2
  3634.     status = MarkBitmap(fdNum, *blockNumPtr - 
  3635.                 domainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK, 
  3636. d1197 1
  3637. a1197 1
  3638.     if (status >= 0) {
  3639. d1205 1
  3640. a1205 1
  3641.         perror("ProcessIndirectBlock: Read failed");
  3642. d1207 2
  3643. d1212 1
  3644. a1212 1
  3645.         fprintf(stderr,
  3646. a1220 1
  3647.     foundError = 1;
  3648. d1225 34
  3649. a1258 1
  3650.     for (i = 0, indexPtr = (int *) indirectBlock; 
  3651. d1261 2
  3652. a1262 1
  3653.     if (*indexPtr == FS_NIL_INDEX) {
  3654. d1264 4
  3655. a1267 1
  3656.         return(-1);
  3657. d1270 5
  3658. a1274 5
  3659.     }
  3660.     if (*indexPtr & (FS_FRAGMENTS_PER_BLOCK - 1)) {
  3661.         if (verbose || lastErrorFD != fdNum) {
  3662.         fprintf(stderr, 
  3663.         "Non-direct block fragmented for file %d.  Block deleted.\n",
  3664. d1276 6
  3665. a1281 6
  3666.         lastErrorFD = fdNum;
  3667.         }
  3668.         foundError = 1;
  3669.         status = -1;
  3670.     } else {
  3671.         status = MarkBitmap(fdNum, *indexPtr, 
  3672. d1284 8
  3673. d1307 2
  3674. a1308 2
  3675.         perror("ProcessIndirectBlock: Write failed");
  3676.         exit(EXIT_HARD_ERR);
  3677. d1312 2
  3678. a1313 44
  3679.  
  3680.     return(0);
  3681. }
  3682.  
  3683.  
  3684. /*
  3685.  *----------------------------------------------------------------------
  3686.  *
  3687.  * MarkBitmap --
  3688.  *
  3689.  *    Mark the bits in the bit map.
  3690.  *    update the cylinder map to reflect which blocks are allocated.
  3691.  *
  3692.  * Results:
  3693.  *    -1 if couldn't mark the bitmap, 0 otherwise.
  3694.  *
  3695.  * Side effects:
  3696.  *    None.
  3697.  *
  3698.  *----------------------------------------------------------------------
  3699.  */
  3700. int
  3701. MarkBitmap(fdNum, blockNum, bitmapPtr, numFrags, domainPtr)
  3702.     int          fdNum;
  3703.     int          blockNum;
  3704.     unsigned char *bitmapPtr;
  3705.     int          numFrags;
  3706.     FsDomainHeader  *domainPtr;
  3707. {
  3708.     register    unsigned char     *bytePtr;
  3709.     register    unsigned char     *bitmaskPtr;
  3710.     unsigned     char              bitmask;
  3711.     int                i;
  3712.     int                fullBlockNum;
  3713.     int                fragOffset;
  3714.  
  3715.     if (blockNum >= num1KBlocks) {
  3716.     if (verbose || lastErrorFD != fdNum) {
  3717.         fprintf(stderr, "Block pointer %d too large for fd %d\n", 
  3718.                blockNum, fdNum);
  3719.         lastErrorFD = fdNum;
  3720.     }
  3721.     foundError = 1;
  3722.     return(-1);
  3723. a1314 36
  3724.     if (blockNum / FS_FRAGMENTS_PER_BLOCK < 
  3725.     (blockNum + numFrags - 1) / FS_FRAGMENTS_PER_BLOCK) {
  3726.     if (verbose || lastErrorFD != fdNum) {
  3727.         fprintf(stderr, 
  3728.                "Block %d extends past block boundary for fd %d\n",
  3729.                blockNum, fdNum);
  3730.         lastErrorFD = fdNum;
  3731.     }
  3732.  
  3733.     foundError = 1;
  3734.     return(-1);
  3735.     }
  3736.     bitmask = 0;
  3737.     fullBlockNum = blockNum / FS_FRAGMENTS_PER_BLOCK;
  3738.     bytePtr = GetBitmapPtr(domainPtr, bitmapPtr, fullBlockNum);
  3739.     fragOffset = blockNum & 0x3;
  3740.     if ((fullBlockNum % domainPtr->geometry.blocksPerCylinder) & 0x1) {
  3741.     fragOffset += 4;
  3742.     }
  3743.     bitmaskPtr = &bitmasks[fragOffset];
  3744.  
  3745.     for (i = 0; i < numFrags; i++, bitmaskPtr++) {
  3746.     if (*bitmaskPtr & *bytePtr) { 
  3747.         if (verbose || lastErrorFD != fdNum) {
  3748.         fprintf(stderr,
  3749.     "File %d references previously allocated block.  Block %d deleted.\n", 
  3750.                fdNum, blockNum + i);
  3751.         lastErrorFD = fdNum;
  3752.         }
  3753.  
  3754.         foundError = 1;
  3755.         return(-1);
  3756.     }
  3757.     bitmask |= *bitmaskPtr;
  3758.     }
  3759.     *bytePtr |= bitmask;
  3760. d1391 1
  3761. a1391 1
  3762.         fprintf(stderr, "RelocateFD: out of file descriptors.\n");
  3763. d1408 5
  3764. d1414 245
  3765. @
  3766.  
  3767.  
  3768. 1.24
  3769. log
  3770. @Changed it to print much less about errors unless verbose is on.
  3771. @
  3772. text
  3773. @d2 1
  3774. a2 1
  3775.  * checkFS.c --
  3776. d11 1
  3777. a11 1
  3778. static char rcsid[] = "$Header: checkFS.c,v 1.23 88/09/20 13:38:04 douglis Exp $ SPRITE (Berkeley)";
  3779. a13 1
  3780. #include "sprite.h"
  3781. d15 1
  3782. a15 1
  3783. #include "io.h"
  3784. d17 6
  3785. a22 4
  3786. #include "checkFS.h"
  3787. #include "mem.h"
  3788. #include "string.h"
  3789. #include "byte.h"
  3790. d28 2
  3791. a29 2
  3792. Boolean    foundError = FALSE;
  3793. Boolean    fdBitmapError = FALSE;
  3794. d33 1
  3795. a33 1
  3796.  * checkFS -D rsd0 -P b
  3797. d44 8
  3798. a51 8
  3799. Boolean patchHeader = FALSE;
  3800. Boolean    writeDisk = FALSE;
  3801. Boolean verbose = FALSE;
  3802. Boolean silent = FALSE;
  3803. Boolean clearDomainNumber = FALSE;
  3804. Boolean recoveryCheck = FALSE;
  3805. Boolean    badBlockInit = FALSE;
  3806. Boolean patchRoot = FALSE;
  3807. d54 1
  3808. a54 1
  3809.     {OPT_STRING, 'D', (Address)&deviceName,
  3810. d56 1
  3811. a56 1
  3812.     {OPT_STRING, 'P', (Address)&partName,
  3813. d58 1
  3814. a58 1
  3815.     {OPT_STRING, 'd', (Address)&devDirectory,
  3816. d60 1
  3817. a60 1
  3818.     {OPT_STRING, 'p', (Address)&firstPartName,
  3819. d62 7
  3820. a68 7
  3821.     {OPT_TRUE, 'W', (Address)&writeDisk,
  3822.     "Write disk (FALSE)"},
  3823.     {OPT_TRUE, 'S', (Address)&silent,
  3824.     "Don't say anything unless there's a problem (FALSE)"},
  3825.     {OPT_TRUE, 'V', (Address)&verbose,
  3826.     "Output information about differences in bitmaps (FALSE)"},
  3827.     {OPT_TRUE, 'r', (Address)&recoveryCheck,
  3828. d70 1
  3829. a70 1
  3830.     {OPT_TRUE, 'R', (Address)&patchRoot,
  3831. d72 1
  3832. a72 1
  3833.     {OPT_TRUE, 'c', (Address)&clearDomainNumber,
  3834. d74 1
  3835. a74 1
  3836.     {OPT_TRUE, 'H', (Address)&patchHeader,
  3837. d76 1
  3838. a76 1
  3839.     {OPT_TRUE, 'b', (Address)&badBlockInit,
  3840. d85 2
  3841. a86 2
  3842. Boolean        RecoveryCheck();
  3843. static Boolean    incVersionNumbers;
  3844. d118 5
  3845. a122 8
  3846.     ReturnStatus status;    /* status of system calls */
  3847.     int firstPartFID;        /* File ID for first parition on the disk */
  3848.     int partFID;        /* File ID for partiton to format */
  3849.     char firstPartitionName[64];
  3850.     char partitionName[64];
  3851.     int partition;        /* Index of partition derived from the
  3852.                  * partition name */
  3853.     int    flags;
  3854. d124 1
  3855. a124 1
  3856.     (void)Opt_Parse(&argc, argv, numOptions, optionArray);
  3857. d127 2
  3858. a128 2
  3859.     Io_Print("Specify device name with -D option\n");
  3860.     Proc_Exit(EXIT_HARD_ERR);
  3861. d131 2
  3862. a132 2
  3863.     Io_Print("Specify partition with -P option\n");
  3864.     Proc_Exit(EXIT_HARD_ERR);
  3865. d139 6
  3866. a144 6
  3867.     (void)String_Copy(devDirectory, firstPartitionName);  /* eg. /dev/ */
  3868.     (void)String_Copy(devDirectory, partitionName);    
  3869.     (void)String_Cat(deviceName, firstPartitionName);      /* eg. /dev/rxy0 */
  3870.     (void)String_Cat(deviceName, partitionName);    
  3871.     (void)String_Cat(firstPartName, firstPartitionName);  /* eg. /dev/rxy0a */
  3872.     (void)String_Cat(partName, partitionName);          /* eg. /dev/rxy0b */
  3873. d146 4
  3874. a149 4
  3875.     status = Fs_Open(firstPartitionName, FS_READ, 0, &firstPartFID);
  3876.     if (status != SUCCESS) {
  3877.     Stat_PrintMsg(status, "checkFS: Can't open first parition");
  3878.     Proc_Exit(EXIT_HARD_ERR);
  3879. d151 4
  3880. a154 3
  3881.     flags = FS_READ;
  3882.     if (writeDisk) {
  3883.     flags |= FS_WRITE;
  3884. a155 5
  3885.     status = Fs_Open(partitionName, flags, 0, &partFID);
  3886.     if (status != SUCCESS) {
  3887.     Stat_PrintMsg(status, "checkFS: Can't open partition to check ");
  3888.     Proc_Exit(EXIT_HARD_ERR);
  3889.     }
  3890. d159 1
  3891. a159 1
  3892.     Io_PrintStream(io_StdErr,
  3893. d161 1
  3894. a161 1
  3895.     Proc_Exit(EXIT_HARD_ERR);
  3896. d165 2
  3897. a166 2
  3898.     (void)Fs_Close(firstPartFID);
  3899.     (void)Fs_Close(partFID);
  3900. d168 1
  3901. a168 1
  3902.     Proc_Exit(EXIT_SOFT_ERR);
  3903. d170 1
  3904. a170 1
  3905.     Proc_Exit(EXIT_OK);
  3906. d219 1
  3907. a219 1
  3908. #define FILE_DESC_PER_SECTOR (FS_FILE_DESC_PER_BLOCK / SECTORS_PER_BLOCK)
  3909. d243 1
  3910. a243 2
  3911.     ReturnStatus            status;
  3912.     BasicDiskInfo           *diskInfoPtr;
  3913. d255 2
  3914. a256 2
  3915.     Boolean            valid;
  3916.     Boolean            salvage;
  3917. d261 1
  3918. a261 1
  3919.     Boolean            bitmapError = FALSE;
  3920. d268 4
  3921. a271 5
  3922.     diskInfoPtr = ReadBasicDiskInfo(firstPartFID, partition);
  3923.     if (diskInfoPtr == (BasicDiskInfo *) NULL) {
  3924.     Io_PrintStream(io_StdErr, 
  3925.             "CheckFilesystem: Could not read basic disk info\n");
  3926.     Proc_Exit(EXIT_HARD_ERR);
  3927. d273 2
  3928. a274 2
  3929.     Io_Flush(io_StdErr);
  3930.     Io_Flush(io_StdOut);
  3931. d276 1
  3932. a276 1
  3933.     domainPtr = (FsDomainHeader *) Mem_Alloc(diskInfoPtr->numDomainSectors *
  3934. d284 2
  3935. a285 2
  3936.     int spriteID;
  3937.     Fs_Attributes attrs;
  3938. d293 8
  3939. a300 3
  3940.     Fs_GetAttributesID(firstPartFID, &attrs);
  3941.     if (attrs.devServerID == FS_LOCALHOST_ID) {
  3942.         Sys_GetMachineInfo(NULL, NULL, &spriteID);
  3943. d302 1
  3944. a302 1
  3945.         spriteID = attrs.devServerID;
  3946. d305 1
  3947. a305 1
  3948.         Io_PrintStream(io_StdErr, "Setting hostID in disk header to 0x%x\n",
  3949. d309 1
  3950. a309 1
  3951.         patchHeader = FALSE;
  3952. d319 2
  3953. a320 3
  3954.       (unsigned char *)Mem_Alloc(domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  3955.     Byte_Zero(domainPtr->bitmapBlocks * FS_BLOCK_SIZE, 
  3956.           (Address) newCylBitmapPtr);
  3957. d324 2
  3958. a325 2
  3959.     descInfoPtr = (FdInfo *) Mem_Alloc(domainPtr->numFileDesc * sizeof(FdInfo));
  3960.     Byte_Zero(domainPtr->numFileDesc * sizeof(FdInfo), (Address)descInfoPtr);
  3961. d337 1
  3962. a337 1
  3963.     Io_PrintStream(io_StdErr, "Performing recovery check\n");
  3964. d340 1
  3965. a340 1
  3966.         Io_PrintStream(io_StdErr, "Disk not safely synced.  Will increment all version numbers.\n");
  3967. d343 1
  3968. a343 1
  3969.     incVersionNumbers = FALSE;
  3970. d352 1
  3971. a352 1
  3972.     Io_PrintStream(io_StdErr, "Checking file descriptors:\n");
  3973. d363 2
  3974. a364 3
  3975.     status = BlockRead(partFID, domainPtr, domainPtr->fileDescOffset + i,
  3976.                 1, (Address) block);
  3977.     if (status != SUCCESS) {
  3978. d369 1
  3979. a369 1
  3980.         Stat_PrintMsg(status, "CheckFilesystem: BlockRead: Read failed");
  3981. d374 1
  3982. a374 3
  3983.         salvage = TRUE;
  3984.                       
  3985.  
  3986. d377 2
  3987. a378 2
  3988.         salvage = FALSE;
  3989.         valid = TRUE;
  3990. d380 1
  3991. a380 1
  3992.     for (sector = 0; sector < SECTORS_PER_BLOCK; sector++) {
  3993. d389 1
  3994. a389 1
  3995.         Boolean    modified = FALSE;
  3996. d414 1
  3997. a414 1
  3998.                 Mem_Alloc(sizeof(RelocListElement));
  3999. d417 2
  4000. a418 2
  4001.             Byte_Copy(sizeof(FsFileDescriptor), (Address)fdPtr,
  4002.                   (Address)&relocElemPtr->fd);
  4003. d448 1
  4004. a448 1
  4005.             modified = TRUE;
  4006. d455 1
  4007. a455 1
  4008.                 (ModListElement *)Mem_Alloc(sizeof(ModListElement));
  4009. d457 2
  4010. a458 2
  4011.             Byte_Copy(sizeof(FsFileDescriptor), (Address)fdPtr,
  4012.                     (Address)&modElemPtr->fd);
  4013. d463 1
  4014. a463 1
  4015.         status = BlockWrite(partFID, domainPtr,
  4016. d465 3
  4017. a467 4
  4018.                     1, (Address) block);
  4019.         if (status != SUCCESS) {
  4020.             Stat_PrintMsg(status, "CheckFileSystem: FD write failed");
  4021.             Proc_Exit(EXIT_HARD_ERR);
  4022. d474 1
  4023. a474 1
  4024.     Io_PrintStream(io_StdErr, "Found error in file descriptor bitmap\n");
  4025. d481 1
  4026. a481 2
  4027.     Io_PrintStream(io_StdErr,
  4028.                "\nComparing old and new data block bit maps:\n");
  4029. d492 1
  4030. a492 1
  4031.             Io_PrintStream(io_StdErr,"Block %d: old %x new %x.\n",
  4032. d496 2
  4033. a497 2
  4034.         foundError = TRUE;
  4035.         bitmapError = TRUE;
  4036. d501 1
  4037. a501 1
  4038.             Io_PrintStream(io_StdErr,"Block %d: old %x new %x.\n",
  4039. d505 2
  4040. a506 2
  4041.         foundError = TRUE;
  4042.         bitmapError = TRUE;
  4043. d511 1
  4044. a511 1
  4045.     Io_PrintStream(io_StdErr, "Found error in data block bitmap\n");
  4046. d513 1
  4047. a513 1
  4048.     Io_Flush(io_StdErr);
  4049. d532 1
  4050. a532 1
  4051.     Io_PrintStream(io_StdErr, "\nTraversing directory tree:\n\n");
  4052. d540 1
  4053. a540 1
  4054.     Io_PrintStream(io_StdOut, 
  4055. d550 1
  4056. a550 1
  4057.     Io_PrintStream(io_StdErr, "Writing disk\n");
  4058. d552 1
  4059. a552 1
  4060.     Io_Flush(io_StdErr);
  4061. d592 4
  4062. a595 3
  4063.     int partFID;        /* Handle on raw disk */
  4064.     BasicDiskInfo *diskInfoPtr;    /* Information from the super block */
  4065.     FsDomainHeader *domainPtr;    /* Reference to domain header to fill in */
  4066. d597 4
  4067. a600 7
  4068.     register ReturnStatus status;    /* General return code. */
  4069.  
  4070.     status = SectorRead(partFID, diskInfoPtr->domainSector,
  4071.             diskInfoPtr->numDomainSectors, (Address)domainPtr);
  4072.     if (status != SUCCESS) {
  4073.     Stat_PrintMsg(status, "ReadDomainHeader: Read failed");
  4074.     Proc_Exit(EXIT_HARD_ERR);
  4075. d622 4
  4076. a625 3
  4077.     int partFID;        /* Handle on raw disk */
  4078.     BasicDiskInfo *diskInfoPtr;    /* Information from the super block */
  4079.     FsDomainHeader *domainPtr;    /* Reference to domain header to fill in */
  4080. d627 4
  4081. a630 7
  4082.     register ReturnStatus status;    /* General return code. */
  4083.  
  4084.     status = SectorWrite(partFID, diskInfoPtr->domainSector,
  4085.             diskInfoPtr->numDomainSectors, (Address)domainPtr);
  4086.     if (status != SUCCESS) {
  4087.     Stat_PrintMsg(status, "WriteDomainHeader: Write failed");
  4088.     Proc_Exit(EXIT_HARD_ERR);
  4089. d652 1
  4090. a652 1
  4091.     register FsDomainHeader *domainPtr;
  4092. a653 1
  4093.     ReturnStatus status;
  4094. d659 1
  4095. a659 1
  4096.     bitmap =(unsigned char *)Mem_Alloc(domainPtr->fdBitmapBlocks*FS_BLOCK_SIZE);
  4097. d661 4
  4098. a664 5
  4099.     status = BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
  4100.                 domainPtr->fdBitmapBlocks, (Address)bitmap);
  4101.     if (status != SUCCESS) {
  4102.     Stat_PrintMsg(status, "ReadFileDescBitmap: Read failed");
  4103.     Proc_Exit(EXIT_HARD_ERR);
  4104. d687 3
  4105. a689 3
  4106.     int                partFID;
  4107.     register FsDomainHeader     *domainPtr;
  4108.     register unsigned char     *bitmap;
  4109. d691 4
  4110. a694 7
  4111.     ReturnStatus    status;
  4112.  
  4113.     status = BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  4114.               domainPtr->fdBitmapBlocks, (Address)bitmap);
  4115.     if (status != SUCCESS) {
  4116.     Stat_PrintMsg(status, "WriteFileDescBitmap: Write failed");
  4117.     Proc_Exit(EXIT_HARD_ERR);
  4118. d716 2
  4119. a717 2
  4120.     int partFID;
  4121.     register FsDomainHeader *domainPtr;
  4122. a718 1
  4123.     ReturnStatus status;
  4124. d721 1
  4125. a721 1
  4126.     bitmap = (unsigned char *)Mem_Alloc(domainPtr->bitmapBlocks*FS_BLOCK_SIZE);
  4127. d723 4
  4128. a726 5
  4129.     status = BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
  4130.                 domainPtr->bitmapBlocks, (Address) bitmap);
  4131.     if (status != SUCCESS) {
  4132.     Stat_PrintMsg(status, "ReadBitmap: Read failed");
  4133.     Proc_Exit(EXIT_HARD_ERR);
  4134. d740 1
  4135. a740 1
  4136.  *    A return status.
  4137. d749 3
  4138. a751 3
  4139.     int partFID;
  4140.     register FsDomainHeader *domainPtr;
  4141.     unsigned char *bitmap;
  4142. d753 4
  4143. a756 7
  4144.     ReturnStatus    status;
  4145.  
  4146.     status = BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  4147.               domainPtr->bitmapBlocks, (Address) bitmap);
  4148.     if (status != SUCCESS) {
  4149.     Stat_PrintMsg(status, "WriteBitmap: Write failed");
  4150.     Proc_Exit(EXIT_HARD_ERR);
  4151. d778 7
  4152. a784 4
  4153.     int             partFID;
  4154.     register FsDomainHeader     *domainPtr;
  4155.     List_Links            *listPtr;
  4156.     FdInfo *descInfoPtr;        
  4157. a786 1
  4158.     ReturnStatus     status;
  4159. d791 1
  4160. a791 1
  4161.     Boolean        badBlock;
  4162. d794 1
  4163. a794 1
  4164.     badBlock = FALSE;
  4165. d806 4
  4166. a809 5
  4167.         status = BlockRead(partFID, domainPtr, blockNum, 1,
  4168.                    (Address) block);
  4169.         if (status != SUCCESS) {
  4170.         Stat_PrintMsg(status, "WriteFileDesc: Warning: read failed");
  4171.         badBlock = TRUE;
  4172. d812 1
  4173. a812 1
  4174.         badBlock = TRUE;
  4175. d818 6
  4176. a823 6
  4177.     Byte_Copy(sizeof(FsFileDescriptor), 
  4178.               (Address) &modElemPtr->fd, (Address) &block[offset]);
  4179.     status = BlockWrite(partFID, domainPtr, blockNum, 1, (Address) block);
  4180.     if (status != SUCCESS) {
  4181.         Stat_PrintMsg(status, "WriteFileDesc: Write failed");
  4182.         Proc_Exit(EXIT_HARD_ERR);
  4183. d846 6
  4184. a851 5
  4185.     int partFID;        /* Handle on raw disk */
  4186.     BasicDiskInfo *diskInfoPtr;    /* Information from the super block */
  4187.     FsDomainHeader *domainPtr;    /* Reference to domain header to fill in */
  4188.     int        numKblocks;    /* Number of 1 Kbyte blocks. */
  4189.     int        numFiles;    /* Number of files. */
  4190. d853 1
  4191. a853 2
  4192.     register ReturnStatus status;    /* General return code. */
  4193.     char    buffer[DEV_BYTES_PER_SECTOR];
  4194. d856 3
  4195. a858 4
  4196.     status = SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer);
  4197.     if (status != SUCCESS) {
  4198.     Stat_PrintMsg(status, "WriteSummaryInfo: Read failed");
  4199.     Proc_Exit(EXIT_HARD_ERR);
  4200. d869 3
  4201. a871 4
  4202.     status = SectorWrite(partFID, diskInfoPtr->summarySector, 1, buffer);
  4203.     if (status != SUCCESS) {
  4204.     Stat_PrintMsg(status, "WriteSummaryInfo: Write failed");
  4205.     Proc_Exit(EXIT_HARD_ERR);
  4206. d885 1
  4207. a885 1
  4208.  *    Return TRUE if the disk not safely synced.
  4209. d892 1
  4210. a892 1
  4211. Boolean
  4212. d895 1
  4213. a895 1
  4214.     BasicDiskInfo    *diskInfoPtr;    /* Information from the super block */
  4215. a896 1
  4216.     register ReturnStatus    status;
  4217. d900 3
  4218. a902 4
  4219.     status = SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer);
  4220.     if (status != SUCCESS) {
  4221.     Stat_PrintMsg(status, "RecoveryCheck: Summary sector read failed");
  4222.     Proc_Exit(EXIT_HARD_ERR);
  4223. d929 7
  4224. a935 4
  4225.     register    FsDomainHeader     *domainPtr;
  4226.     int                 fdNum;
  4227.     Address             block;
  4228.     register    unsigned char      **bitmapPtrPtr;
  4229. d939 1
  4230. a939 1
  4231.     Boolean               allocated;
  4232. d954 1
  4233. a954 1
  4234.             Io_PrintStream(io_StdErr,
  4235. d958 2
  4236. a959 2
  4237.         foundError = TRUE;
  4238.         fdBitmapError = TRUE;
  4239. d963 1
  4240. a963 1
  4241.             Io_PrintStream(io_StdErr,
  4242. d967 2
  4243. a968 2
  4244.         foundError = TRUE;
  4245.         fdBitmapError = TRUE;
  4246. a991 1
  4247.  
  4248. d994 4
  4249. a997 3
  4250.     register    FsDomainHeader     *domainPtr;
  4251.     int                 fdNum;
  4252.     register    unsigned char      **bitmapPtrPtr;
  4253. d1013 1
  4254. d1033 9
  4255. a1041 6
  4256.     int         partFID;
  4257.     FsDomainHeader    *domainPtr;
  4258.     int            fdNum;
  4259.     FsFileDescriptor    *fdPtr;
  4260.     unsigned char     *newCylBitmapPtr;
  4261.     Boolean        *modifiedPtr;
  4262. a1045 1
  4263.     ReturnStatus         status;
  4264. d1050 1
  4265. a1050 1
  4266.     Boolean            dirty;
  4267. d1053 1
  4268. d1078 1
  4269. a1078 1
  4270.             Io_PrintStream(io_StdErr, 
  4271. d1084 1
  4272. a1084 1
  4273.         *modifiedPtr = TRUE;
  4274. d1091 1
  4275. a1091 1
  4276.         if (status == SUCCESS) {
  4277. d1102 1
  4278. a1102 1
  4279.             Io_PrintStream(io_StdErr,
  4280. d1107 2
  4281. a1108 2
  4282.             foundError = TRUE;
  4283.             status = FAILURE;
  4284. d1113 1
  4285. a1113 1
  4286.             if (status == SUCCESS) {
  4287. d1119 1
  4288. a1119 1
  4289.         if (status != SUCCESS) {
  4290. d1121 1
  4291. a1121 1
  4292.         *modifiedPtr = TRUE;
  4293. d1127 1
  4294. a1127 1
  4295.         Io_PrintStream(io_StdErr, "Hole in directory %d.\n", fdNum);
  4296. d1136 1
  4297. a1136 1
  4298.         Io_PrintStream(io_StdErr, "Missing last block in file %d.\n",
  4299. d1152 1
  4300. a1152 1
  4301.         Io_PrintStream(io_StdErr,
  4302. d1168 1
  4303. a1168 1
  4304.     if (status == DIR_HOLE) {
  4305. d1170 1
  4306. a1170 1
  4307.         Io_PrintStream(io_StdErr, 
  4308. a1175 3
  4309.     } else if (status != SUCCESS) {
  4310.         Sys_Panic(SYS_FATAL,
  4311.             "CheckBlocks: Bad status from ProcessIndirectBlock\n");
  4312. d1182 1
  4313. a1182 1
  4314.         Io_PrintStream(io_StdErr, 
  4315. d1193 1
  4316. a1193 1
  4317.         Io_PrintStream(io_StdErr,
  4318. d1207 1
  4319. a1207 1
  4320.         Io_PrintStream(io_StdErr, 
  4321. d1212 2
  4322. a1213 2
  4323.     foundError = TRUE;
  4324.     status = FAILURE;
  4325. d1220 1
  4326. a1220 1
  4327.     if (status == SUCCESS) {
  4328. d1224 1
  4329. a1224 1
  4330.     status = BlockRead(partFID, domainPtr, 
  4331. d1226 3
  4332. a1228 4
  4333.                1, (Address) dblIndirectBlock);
  4334.     if (status != SUCCESS) {
  4335.         Stat_PrintMsg(status, "CheckBlocks: Read failed");
  4336.         Proc_Exit(EXIT_HARD_ERR);
  4337. d1236 1
  4338. a1236 1
  4339.             Io_PrintStream(io_StdErr, 
  4340. d1252 1
  4341. a1252 1
  4342.         if (status == DIR_HOLE) {
  4343. d1254 1
  4344. a1254 1
  4345.             Io_PrintStream(io_StdErr, 
  4346. a1259 3
  4347.         } else if (status != SUCCESS) {
  4348.         Sys_Panic(SYS_FATAL,
  4349.             "CheckBlocks: Bad status from ProcessIndirectBlock (2)\n");
  4350. d1265 1
  4351. a1265 1
  4352.         status = BlockWrite(partFID, domainPtr, 
  4353. d1267 3
  4354. a1269 4
  4355.                1, (Address) dblIndirectBlock);
  4356.         if (status != SUCCESS) {
  4357.             Stat_PrintMsg(status, "CheckBlocks: Write failed");
  4358.             Proc_Exit(EXIT_HARD_ERR);
  4359. d1275 1
  4360. a1275 1
  4361.     *modifiedPtr = TRUE;
  4362. d1289 1
  4363. a1289 1
  4364.     Io_PrintStream(io_StdErr,"Truncating file %d to length %d\n", fdNum,
  4365. d1291 2
  4366. a1292 2
  4367.     foundError = TRUE;
  4368.     *modifiedPtr = TRUE;
  4369. d1298 1
  4370. a1298 1
  4371.         Io_PrintStream(io_StdErr,
  4372. d1304 2
  4373. a1305 2
  4374.     foundError = TRUE;
  4375.     *modifiedPtr = TRUE;
  4376. d1323 1
  4377. a1323 1
  4378.         Io_PrintStream(io_StdErr, 
  4379. d1329 1
  4380. a1329 1
  4381.         *modifiedPtr = TRUE;
  4382. d1344 2
  4383. a1345 1
  4384.  *    FAILURE if could not read in the indirect block.
  4385. d1352 1
  4386. a1352 2
  4387.  
  4388. ReturnStatus
  4389. d1367 1
  4390. a1367 1
  4391.     Boolean        *dirtyPtr;      /* TRUE if *blockNumPtr gets 
  4392. d1372 1
  4393. a1372 1
  4394.     Boolean        *modifiedPtr;       /* TRUE if the file descriptor
  4395. d1380 2
  4396. a1381 2
  4397.     ReturnStatus    status;
  4398.     Boolean        dirty = FALSE;
  4399. d1385 1
  4400. a1385 1
  4401.         Io_PrintStream(io_StdErr, 
  4402. d1390 2
  4403. a1391 2
  4404.     foundError = TRUE;
  4405.     status = FAILURE;
  4406. d1398 1
  4407. a1398 1
  4408.     if (status == SUCCESS) {
  4409. d1402 5
  4410. a1406 5
  4411.         status = BlockRead(partFID, domainPtr, 
  4412.                *blockNumPtr / FS_FRAGMENTS_PER_BLOCK, 1, 
  4413.                (Address) indirectBlock);
  4414.     if (status != SUCCESS) {
  4415.         Stat_PrintMsg(status, "ProcessIndirectBlock: Read failed");
  4416. d1409 1
  4417. a1409 1
  4418.     if (status != SUCCESS) {
  4419. d1411 1
  4420. a1411 1
  4421.         Io_PrintStream(io_StdErr,
  4422. d1418 4
  4423. a1421 4
  4424.     *dirtyPtr = TRUE;
  4425.     *modifiedPtr = TRUE;
  4426.     foundError = TRUE;
  4427.     return(SUCCESS);
  4428. d1423 1
  4429. a1423 1
  4430.     *dirtyPtr = FALSE;
  4431. d1430 1
  4432. a1430 1
  4433.         return(DIR_HOLE);
  4434. d1436 1
  4435. a1436 1
  4436.         Io_PrintStream(io_StdErr, 
  4437. d1441 2
  4438. a1442 2
  4439.         foundError = TRUE;
  4440.         status = FAILURE;
  4441. d1448 1
  4442. a1448 1
  4443.     if (status == SUCCESS) {
  4444. d1454 1
  4445. a1454 1
  4446.         dirty = TRUE;
  4447. d1459 1
  4448. a1459 1
  4449.         status = BlockWrite(partFID, domainPtr, 
  4450. d1461 3
  4451. a1463 4
  4452.                 1, (Address) indirectBlock);
  4453.         if (status != SUCCESS) {
  4454.         Stat_PrintMsg(status, "ProcessIndirectBlock: Write failed");
  4455.         Proc_Exit(EXIT_HARD_ERR);
  4456. d1468 1
  4457. a1468 1
  4458.     return(SUCCESS);
  4459. d1481 1
  4460. a1481 1
  4461.  *    FAILURE if could not read in the indirect block.
  4462. d1488 1
  4463. a1488 2
  4464.  
  4465. ReturnStatus
  4466. d1505 1
  4467. a1505 1
  4468.         Io_PrintStream(io_StdErr, "Block pointer %d too large for fd %d\n", 
  4469. d1509 2
  4470. a1510 2
  4471.     foundError = TRUE;
  4472.     return(FAILURE);
  4473. d1515 1
  4474. a1515 1
  4475.         Io_PrintStream(io_StdErr, 
  4476. d1521 2
  4477. a1522 2
  4478.     foundError = TRUE;
  4479.     return(FAILURE);
  4480. d1536 1
  4481. a1536 1
  4482.         Io_PrintStream(io_StdErr,
  4483. d1542 2
  4484. a1543 2
  4485.         foundError = TRUE;
  4486.         return(FAILURE);
  4487. d1548 1
  4488. a1548 1
  4489.     return(SUCCESS);
  4490. d1585 2
  4491. a1586 2
  4492.     Boolean               found = FALSE;
  4493.     static Boolean           outOfDescriptors = FALSE;
  4494. d1606 1
  4495. a1606 1
  4496.         found = TRUE;
  4497. d1624 2
  4498. a1625 1
  4499.         Sys_Panic(SYS_WARNING, "RelocateFD: out of file descriptors.\n");
  4500. d1627 1
  4501. a1627 1
  4502.         outOfDescriptors = TRUE;
  4503. @
  4504.  
  4505.  
  4506. 1.23
  4507. log
  4508. @Made messages about file descriptor bit map only be printed if are in
  4509. verbose mode.
  4510. @
  4511. text
  4512. @d11 1
  4513. a11 1
  4514. static char rcsid[] = "$Header: checkFS.c,v 1.22 88/07/19 11:45:46 douglis Exp $ SPRITE (Berkeley)";
  4515. d28 1
  4516. d87 5
  4517. d265 4
  4518. d270 1
  4519. d481 4
  4520. d488 1
  4521. a488 5
  4522.     if (verbose) {
  4523.         unsigned char     *oldPtr;
  4524.     unsigned char     *newPtr;
  4525.     int        blockNum;
  4526.  
  4527. d490 14
  4528. a503 17
  4529.             "\nComparing old and new data block bit maps\n");
  4530.     for (oldPtr = cylBitmapPtr, newPtr = newCylBitmapPtr, 
  4531.                                 i = 0, blockNum = 0; 
  4532.         i < domainPtr->dataCylinders; 
  4533.         i++, oldPtr = &cylBitmapPtr[bytesPerCylinder * i], 
  4534.              newPtr = &newCylBitmapPtr[bytesPerCylinder * i]) {
  4535.         for (j = 0; 
  4536.              j < bytesPerCylinder; 
  4537.          j++, oldPtr++, newPtr++, blockNum += 2) {
  4538.              if ((*oldPtr & 0xf0) != (*newPtr & 0xf0)) {
  4539.              Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", blockNum * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0xf0, *newPtr & 0xf0);
  4540.              foundError = TRUE;
  4541.              } 
  4542.              if ((*oldPtr & 0x0f) != (*newPtr & 0x0f)) {
  4543.              Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", (blockNum + 1) * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0x0f, *newPtr & 0x0f);
  4544.              foundError = TRUE;
  4545.              }
  4546. d505 11
  4547. d517 6
  4548. a523 2
  4549.         Io_Flush(io_StdErr);
  4550.     }
  4551. d978 1
  4552. a978 1
  4553.                    "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n",
  4554. d982 1
  4555. d987 1
  4556. a987 1
  4557.                    "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n",
  4558. d991 1
  4559. d1096 2
  4560. a1097 1
  4561.         Io_PrintStream(io_StdErr, 
  4562. d1100 2
  4563. d1120 3
  4564. a1122 1
  4565.             Io_PrintStream(io_StdErr, "Fragmented block that is not the last in file %d. Block deleted.\n",
  4566. d1124 2
  4567. d1145 4
  4568. a1148 1
  4569.         Io_PrintStream(io_StdErr, "Hole in directory %d.\n", fdNum);
  4570. d1154 5
  4571. a1158 2
  4572.         Io_PrintStream(io_StdErr, "Missing last block in file %d.\n",
  4573.                fdNum);
  4574. d1170 6
  4575. a1175 2
  4576.         Io_PrintStream(io_StdErr, "Hole in directory %d because single indirect block is NIL.\n",
  4577.                 fdNum);
  4578. d1188 6
  4579. a1193 2
  4580.         Io_PrintStream(io_StdErr, "Hole in directory %d in single indirect block\n",
  4581.                 fdNum);
  4582. d1203 6
  4583. a1208 2
  4584.         Io_PrintStream(io_StdErr, "Missing last block in singly indirect block for file %d\n",
  4585.                 fdNum);
  4586. d1214 6
  4587. a1219 1
  4588.     Io_PrintStream(io_StdErr, "Last block missing in file %d because doubly indirect block is nil\n", fdNum);
  4589. d1228 6
  4590. a1233 1
  4591.     Io_PrintStream(io_StdErr, "Doubly indirect block on non-block boundary for file %d.  Block deleted.\n", fdNum);
  4592. d1258 6
  4593. a1263 2
  4594.             Io_PrintStream(io_StdErr, "Hole in directory %d in doubly indirect block\n",
  4595.                 fdNum);
  4596. d1276 6
  4597. a1281 2
  4598.         Io_PrintStream(io_StdErr, "Hole in directory %d in doubly indirect blocks (2)\n",
  4599.                    fdNum);
  4600. d1324 6
  4601. a1329 2
  4602.     Io_PrintStream(io_StdErr, "Block count corrected for file %d.  Is %d should be %d.\n", 
  4603.         fdNum, fdPtr->numKbytes, blockCount);
  4604. d1349 2
  4605. a1350 1
  4606.         Io_PrintStream(io_StdErr, 
  4607. d1352 5
  4608. a1356 3
  4609.         i, fdNum, fdPtr->indirect[i]);
  4610.         fdPtr->indirect[i] = FS_NIL_INDEX;
  4611.         *modifiedPtr = TRUE;
  4612. d1411 6
  4613. a1416 1
  4614.     Io_PrintStream(io_StdErr, "Indirect block on a non-block boundary for file %d.  Block deleted.\n", fdNum);
  4615. d1437 6
  4616. a1442 1
  4617.     Io_PrintStream(io_StdErr, "Indirect block (%d) unreadable for file #%d.  Block deleted.\n", *blockNumPtr, fdNum);
  4618. d1462 3
  4619. a1464 1
  4620.         Io_PrintStream(io_StdErr, "Non-direct block fragmented for file %d.  Block deleted.\n",
  4621. d1466 2
  4622. d1533 5
  4623. a1537 2
  4624.     Io_PrintStream(io_StdErr, "Block pointer %d too large for fd %d\n", 
  4625.                blockNum, fdNum);
  4626. d1543 2
  4627. a1544 1
  4628.     Io_PrintStream(io_StdErr, 
  4629. d1547 3
  4630. d1564 3
  4631. a1566 1
  4632.         Io_PrintStream(io_StdErr, "File %d references previously allocated block.  Block %d deleted.\n", 
  4633. d1568 3
  4634. @
  4635.  
  4636.  
  4637. 1.22
  4638. log
  4639. @Added ability to salvage and relocate file descriptors in unreadable
  4640. blocks and to mark those blocks as unuseable (temporarily -- if readable
  4641. again later, they will be reclaimed).
  4642. @
  4643. text
  4644. @d11 1
  4645. a11 1
  4646. static char rcsid[] = "$Header: checkFS.c,v 1.21 88/06/06 12:02:40 brent Exp $ SPRITE (Berkeley)";
  4647. d953 5
  4648. a957 1
  4649.         Io_PrintStream(io_StdErr, "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n", fdNum);
  4650. d961 5
  4651. a965 1
  4652.         Io_PrintStream(io_StdErr, "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n", fdNum);
  4653. @
  4654.  
  4655.  
  4656. 1.21
  4657. log
  4658. @Added code to look for extra blocks, those after lastByte.
  4659. @
  4660. text
  4661. @d11 1
  4662. a11 1
  4663. static char rcsid[] = "$Header: checkFS.c,v 1.20 88/06/02 12:58:50 brent Exp $ SPRITE (Berkeley)";
  4664. d25 1
  4665. d135 6
  4666. a140 6
  4667.     String_Copy(devDirectory, firstPartitionName);    /* eg. /dev/ */
  4668.     String_Copy(devDirectory, partitionName);
  4669.     String_Cat(deviceName, firstPartitionName);        /* eg. /dev/rxy0 */
  4670.     String_Cat(deviceName, partitionName);
  4671.     String_Cat(firstPartName, firstPartitionName);    /* eg. /dev/rxy0a */
  4672.     String_Cat(partName, partitionName);        /* eg. /dev/rxy0b */
  4673. d196 2
  4674. a197 1
  4675. void        CheckBlocks();
  4676. d203 1
  4677. d215 6
  4678. a247 1
  4679.     unsigned    char          *fdBitmapPtr;
  4680. a248 1
  4681.     unsigned    char          *cylBitmapPtr;
  4682. d254 5
  4683. d324 1
  4684. d359 16
  4685. a374 2
  4686.         Stat_PrintMsg(status, "CheckFilesystem: Read failed");
  4687.         Proc_Exit(EXIT_HARD_ERR);
  4688. d376 4
  4689. a379 8
  4690.     CheckFDBitmap(domainPtr, fdNum, block, &tFdBitmapPtr);
  4691.     for (j = 0; 
  4692.          j < FS_FILE_DESC_PER_BLOCK && fdNum < domainPtr->numFileDesc;
  4693.          j++, fdNum++, tDescInfoPtr++, fdPtr++) {
  4694.         Boolean    modified;
  4695.         fdPtr = (FsFileDescriptor *)&block[j * FS_MAX_FILE_DESC_SIZE];
  4696.         if (fdPtr->fileType == FS_DIRECTORY) {
  4697.         tDescInfoPtr->flags |= IS_A_DIRECTORY;
  4698. d381 22
  4699. a402 3
  4700.         if (fdPtr->flags & FS_FD_ALLOC) {
  4701.         if (incVersionNumbers && fdPtr->fileType != FS_DEVICE) {
  4702.             fdPtr->version++;
  4703. d404 17
  4704. a420 18
  4705.         tDescInfoPtr->flags |= FD_ALLOCATED;
  4706.         tDescInfoPtr->origLinkCount = fdPtr->numLinks;
  4707.     
  4708.         modified = FALSE;
  4709.         CheckBlocks(partFID, domainPtr, fdNum, fdPtr,
  4710.                      cylBitmapPtr, newCylBitmapPtr, &modified);
  4711.         } else if (badBlockInit && fdNum == FS_BAD_BLOCK_FILE_NUMBER) {
  4712.         int    index;
  4713.         fdPtr->flags = FS_FD_ALLOC;
  4714.         fdPtr->firstByte = -1;
  4715.         fdPtr->lastByte = -1;
  4716.         fdPtr->numKbytes = 0;
  4717.         fdPtr->fileType = FS_FILE;
  4718.         fdPtr->uid = 0;
  4719.         fdPtr->gid = 0;
  4720.         fdPtr->numLinks = 0;
  4721.         for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
  4722.             fdPtr->direct[index] = FS_NIL_INDEX;
  4723. d422 23
  4724. a444 2
  4725.         for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
  4726.             fdPtr->indirect[index] = FS_NIL_INDEX;
  4727. d446 2
  4728. a447 4
  4729.         modified = TRUE;
  4730.         }
  4731.         if (modified) {
  4732.         ModListElement    *modElemPtr;
  4733. d449 8
  4734. a456 7
  4735.         tDescInfoPtr->flags |= ON_MOD_LIST;
  4736.         modElemPtr =
  4737.             (ModListElement *)Mem_Alloc(sizeof(ModListElement));
  4738.         modElemPtr->fdNum = fdNum;
  4739.         Byte_Copy(sizeof(FsFileDescriptor), (Address)fdPtr,
  4740.                 (Address)&modElemPtr->fd);
  4741.         List_Insert((List_Links *)modElemPtr, LIST_ATREAR(modList));
  4742. d458 8
  4743. a465 8
  4744.     }
  4745.     if (incVersionNumbers && writeDisk) {
  4746.         status = BlockWrite(partFID, domainPtr,
  4747.                 domainPtr->fileDescOffset + i,
  4748.                 1, (Address) block);
  4749.         if (status != SUCCESS) {
  4750.         Stat_PrintMsg(status, "CheckFileSystem: FD write failed");
  4751.         Proc_Exit(EXIT_HARD_ERR);
  4752. d501 4
  4753. d506 7
  4754. d554 2
  4755. a555 1
  4756.     WriteFileDesc(partFID, domainPtr);
  4757. d777 1
  4758. a777 1
  4759. WriteFileDesc(partFID, domainPtr)
  4760. d780 3
  4761. d789 1
  4762. d791 2
  4763. a792 1
  4764.     LIST_FORALL(modList, (List_Links *)modElemPtr) {
  4765. d797 15
  4766. a811 4
  4767.     status = BlockRead(partFID, domainPtr, blockNum, 1, (Address) block);
  4768.     if (status != SUCCESS) {
  4769.         Stat_PrintMsg(status, "WriteFileDesc: Read failed");
  4770.         Proc_Exit(EXIT_HARD_ERR);
  4771. d813 4
  4772. d861 2
  4773. a862 1
  4774.     summaryInfoPtr->numFreeFileDesc = domainPtr->numFileDesc - numFiles;
  4775. d964 1
  4776. d969 38
  4777. d1021 1
  4778. a1021 2
  4779. CheckBlocks(partFID, domainPtr, fdNum, fdPtr, cylBitmapPtr,
  4780.         newCylBitmapPtr, modifiedPtr)
  4781. a1025 1
  4782.     unsigned char     *cylBitmapPtr;
  4783. d1175 3
  4784. d1338 3
  4785. d1469 92
  4786. @
  4787.  
  4788.  
  4789. 1.21.1.1
  4790. log
  4791. @almost works, except when it writes back the descriptor.
  4792. @
  4793. text
  4794. @d11 1
  4795. a11 1
  4796. static char rcsid[] = "$Header: checkFS.c,v 1.21 88/06/06 12:02:40 brent Exp $ SPRITE (Berkeley)";
  4797. a24 1
  4798. int    numBadDesc = 0;
  4799. d134 6
  4800. a139 6
  4801.     (void)String_Copy(devDirectory, firstPartitionName);  /* eg. /dev/ */
  4802.     (void)String_Copy(devDirectory, partitionName);    
  4803.     (void)String_Cat(deviceName, firstPartitionName);      /* eg. /dev/rxy0 */
  4804.     (void)String_Cat(deviceName, partitionName);    
  4805.     (void)String_Cat(firstPartName, firstPartitionName);  /* eg. /dev/rxy0a */
  4806.     (void)String_Cat(partName, partitionName);          /* eg. /dev/rxy0b */
  4807. d195 1
  4808. a195 2
  4809. void        SetBadDescBitmap();
  4810. void        RelocateFD();
  4811. a200 1
  4812. List_Links    relocListHdr;
  4813. a211 6
  4814. /*
  4815.  * Number of file descriptors in a sector, if we have to go through
  4816.  * the sectors individually.
  4817.  */
  4818. #define FILE_DESC_PER_SECTOR (FS_FILE_DESC_PER_BLOCK / SECTORS_PER_BLOCK)
  4819.  
  4820. d239 1
  4821. d241 1
  4822. a246 5
  4823.     int                sector;
  4824.     unsigned int        validMask;
  4825.     Boolean            valid;
  4826.     Boolean            salvage;
  4827.     RelocListElement        *relocElemPtr;
  4828. a311 1
  4829.     List_Init(relocList);
  4830. d346 2
  4831. a347 16
  4832.         /*
  4833.          * Hit a disk error reading the block.  Read it a sector
  4834.          * at a time and try to salvage what we can.
  4835.          */
  4836.         Stat_PrintMsg(status, "CheckFilesystem: BlockRead: Read failed");
  4837.         validMask = Disk_BadBlockRead(partFID, domainPtr,
  4838.                       domainPtr->fileDescOffset + i,
  4839.                       (Address) block);
  4840.         SetBadDescBitmap(domainPtr, fdNum, &tFdBitmapPtr);
  4841.         salvage = TRUE;
  4842.                       
  4843.  
  4844.     } else {
  4845.         CheckFDBitmap(domainPtr, fdNum, block, &tFdBitmapPtr);
  4846.         salvage = FALSE;
  4847.         valid = TRUE;
  4848. d349 8
  4849. a356 4
  4850.     for (sector = 0; sector < SECTORS_PER_BLOCK; sector++) {
  4851.         if (salvage) {
  4852.         valid = (validMask & (1 << sector)) != 0;
  4853.         numBadDesc++;
  4854. d358 3
  4855. a360 22
  4856.         for (j = 0; 
  4857.          j < FILE_DESC_PER_SECTOR && fdNum < domainPtr->numFileDesc;
  4858.          j++, fdNum++, tDescInfoPtr++, fdPtr++) {
  4859.  
  4860.         Boolean    modified = FALSE;
  4861.         fdPtr = (FsFileDescriptor *)
  4862.             &block[(j + (FILE_DESC_PER_SECTOR * sector)) *
  4863.                    FS_MAX_FILE_DESC_SIZE];
  4864.         if (valid) {
  4865.             if (fdPtr->fileType == FS_DIRECTORY) {
  4866.             tDescInfoPtr->flags |= IS_A_DIRECTORY;
  4867.             }
  4868.             if (fdPtr->flags & FS_FD_ALLOC) {
  4869.             if (incVersionNumbers && fdPtr->fileType != FS_DEVICE) {
  4870.                 fdPtr->version++;
  4871.             }
  4872.             tDescInfoPtr->flags |= FD_ALLOCATED;
  4873.             tDescInfoPtr->origLinkCount = fdPtr->numLinks;
  4874.  
  4875.             CheckBlocks(partFID, domainPtr, fdNum, fdPtr,
  4876.                     newCylBitmapPtr, &modified);
  4877.             }
  4878. d362 18
  4879. a379 17
  4880.         if (salvage) {
  4881.             if (valid && (fdPtr->flags & FS_FD_ALLOC)) {
  4882.             RelocListElement    *relocElemPtr;
  4883.  
  4884.             tDescInfoPtr->flags |= FD_RELOCATE;
  4885.             relocElemPtr = (RelocListElement *)
  4886.                 Mem_Alloc(sizeof(RelocListElement));
  4887.             relocElemPtr->origFdNum = fdNum;
  4888.             relocElemPtr->newFdNum = -1;
  4889.             Byte_Copy(sizeof(FsFileDescriptor), (Address)fdPtr,
  4890.                   (Address)&relocElemPtr->fd);
  4891.             List_Insert((List_Links *)relocElemPtr,
  4892.                     LIST_ATREAR(relocList));
  4893.             }
  4894.             if (!valid) {
  4895.             tDescInfoPtr->flags |= FD_UNREADABLE;
  4896.             }
  4897. d381 2
  4898. a382 23
  4899.         /*
  4900.          * Essentially the same code is used to zero out an unuseable
  4901.          * descriptor and to initialize the bad block descriptor.
  4902.          */
  4903.         if ((badBlockInit && fdNum == FS_BAD_BLOCK_FILE_NUMBER) ||
  4904.                 salvage) {
  4905.             int    index;
  4906.  
  4907.             fdPtr->flags = valid ? FS_FD_ALLOC : FS_FD_FREE;
  4908.             fdPtr->firstByte = -1;
  4909.             fdPtr->lastByte = -1;
  4910.             fdPtr->numKbytes = 0;
  4911.             fdPtr->fileType = FS_FILE;
  4912.             fdPtr->uid = 0;
  4913.             fdPtr->gid = 0;
  4914.             fdPtr->numLinks = 0;
  4915.             for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
  4916.             fdPtr->direct[index] = FS_NIL_INDEX;
  4917.             }
  4918.             for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
  4919.             fdPtr->indirect[index] = FS_NIL_INDEX;
  4920.             }
  4921.             modified = TRUE;
  4922. d384 4
  4923. a387 2
  4924.         if (modified) {
  4925.             ModListElement    *modElemPtr;
  4926. d389 7
  4927. a395 8
  4928.             tDescInfoPtr->flags |= ON_MOD_LIST;
  4929.             modElemPtr =
  4930.                 (ModListElement *)Mem_Alloc(sizeof(ModListElement));
  4931.             modElemPtr->fdNum = fdNum;
  4932.             Byte_Copy(sizeof(FsFileDescriptor), (Address)fdPtr,
  4933.                     (Address)&modElemPtr->fd);
  4934.             List_Insert((List_Links *)modElemPtr, LIST_ATREAR(modList));
  4935.         }
  4936. d397 8
  4937. a404 8
  4938.         if (incVersionNumbers && writeDisk) {
  4939.         status = BlockWrite(partFID, domainPtr,
  4940.                     domainPtr->fileDescOffset + i,
  4941.                     1, (Address) block);
  4942.         if (status != SUCCESS) {
  4943.             Stat_PrintMsg(status, "CheckFileSystem: FD write failed");
  4944.             Proc_Exit(EXIT_HARD_ERR);
  4945.         }
  4946. a439 4
  4947.     /*
  4948.      * We now know which descriptors, if any, need to be relocated.  Allocate
  4949.      * new descriptors to hold the information.
  4950.      */
  4951. a440 7
  4952.     if (!(List_IsEmpty(relocList))) {
  4953.     LIST_FORALL(relocList, (List_Links *)relocElemPtr) {
  4954.         RelocateFD(domainPtr, descInfoPtr, relocElemPtr);
  4955.     }
  4956.     }
  4957.     
  4958.  
  4959. d482 1
  4960. a482 2
  4961.     WriteFileDesc(partFID, domainPtr, modList);
  4962.     WriteFileDesc(partFID, domainPtr, relocList);
  4963. d704 1
  4964. a704 1
  4965. WriteFileDesc(partFID, domainPtr, listPtr)
  4966. a706 1
  4967.     List_Links            *listPtr;
  4968. d714 1
  4969. a714 1
  4970.     LIST_FORALL(listPtr, (List_Links *)modElemPtr) {
  4971. d768 1
  4972. a768 2
  4973.     summaryInfoPtr->numFreeFileDesc = domainPtr->numFileDesc - numFiles -
  4974.         numBadDesc;
  4975. a869 1
  4976.  
  4977. a873 38
  4978.  * SetBadDescBitmap --
  4979.  *
  4980.  *    Go through the bitmaps and flag all the bits for this block as
  4981.  *    allocated.
  4982.  *
  4983.  * Results:
  4984.  *    None.
  4985.  *
  4986.  * Side effects:
  4987.  *    None.
  4988.  *
  4989.  *----------------------------------------------------------------------
  4990.  */
  4991.  
  4992. void
  4993. SetBadDescBitmap(domainPtr, fdNum, bitmapPtrPtr)
  4994.     register    FsDomainHeader     *domainPtr;
  4995.     int                 fdNum;
  4996.     register    unsigned char      **bitmapPtrPtr;
  4997. {
  4998.     int                i, j;
  4999.     register unsigned char     *bitmaskPtr;
  5000.  
  5001.     for (i = 0; i < FS_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  5002.         fdNum < domainPtr->numFileDesc;
  5003.          i++, (*bitmapPtrPtr)++){
  5004.     for (j = 0, bitmaskPtr = bitmasks; 
  5005.          j < BITS_PER_BYTE && fdNum < domainPtr->numFileDesc; 
  5006.          j++, fdNum++, bitmaskPtr++) {
  5007.  
  5008.          **bitmapPtrPtr |= *bitmaskPtr;
  5009.      }
  5010.     }
  5011. }
  5012.  
  5013. /*
  5014.  *----------------------------------------------------------------------
  5015.  *
  5016. d888 2
  5017. a889 1
  5018. CheckBlocks(partFID, domainPtr, fdNum, fdPtr, newCylBitmapPtr, modifiedPtr)
  5019. d894 1
  5020. a1331 92
  5021. }
  5022.  
  5023.  
  5024.  
  5025. /*
  5026.  *----------------------------------------------------------------------
  5027.  *
  5028.  * RelocateFD ---
  5029.  *
  5030.  *    Allocate a new file descriptor as close to the old one as possible.
  5031.  *    This is used to relocate descriptors in blocks that get I/O errors.
  5032.  *    This code is based on the kernel routine FsGetNewFileNumber.
  5033.  *    
  5034.  * Results:
  5035.  *    None.
  5036.  *
  5037.  * Side effects:
  5038.  *    The new descriptor is marked as allocated in the bitmap.
  5039.  *
  5040.  *----------------------------------------------------------------------
  5041.  */
  5042.  
  5043. void
  5044. RelocateFD(domainPtr, descInfoPtr, relocPtr)
  5045.     register FsDomainHeader *domainPtr;    /* Domain to allocate the file 
  5046.                      * descriptor out of. */
  5047.     FdInfo *descInfoPtr;        /* information for each file
  5048.                      * descriptor */
  5049.     RelocListElement *relocPtr;        /* Pointer to information for old
  5050.                      * descriptor. */
  5051. {
  5052.     register int            i;
  5053.     register int        j;
  5054.     int                startByte;
  5055.     register unsigned char     *bitmapPtr;
  5056.     register unsigned char     *bitmaskPtr;
  5057.     Boolean               found = FALSE;
  5058.     static Boolean           outOfDescriptors = FALSE;
  5059.     int                   descBytes;
  5060.  
  5061.     /*
  5062.      * If we can't relocate it, chuck it.
  5063.      */
  5064.     if (outOfDescriptors) {
  5065.     descInfoPtr[relocPtr->origFdNum].flags |= FD_UNREADABLE;
  5066.     return;
  5067.     }
  5068.  
  5069.     /*
  5070.      * Linear search forward the bit map a byte at a time.
  5071.      */
  5072.     startByte = relocPtr->origFdNum / BITS_PER_BYTE;
  5073.     bitmapPtr = &fdBitmapPtr[startByte];
  5074.     descBytes = domainPtr->numFileDesc >> 3;
  5075.     i = startByte;
  5076.     do {
  5077.     if (*bitmapPtr != 0xff) {
  5078.         found = TRUE;
  5079.         break;
  5080.     }
  5081.     i++;
  5082.     if (i == descBytes) {
  5083.         i = 0;
  5084.         bitmapPtr = fdBitmapPtr;
  5085.     } else {
  5086.         bitmapPtr++;
  5087.     }
  5088.     } while (i != startByte);
  5089.  
  5090.     if (!found) {
  5091.     /*
  5092.      * Couldn't relocate it, so throw it away and pretend we couldn't
  5093.      * recover it.
  5094.      */
  5095.     if (!outOfDescriptors) {
  5096.         Sys_Panic(SYS_WARNING, "RelocateFD: out of file descriptors.\n");
  5097.     } else {
  5098.         outOfDescriptors = TRUE;
  5099.     }
  5100.     descInfoPtr[relocPtr->origFdNum].flags |= FD_UNREADABLE;
  5101.     return;
  5102.     }
  5103.  
  5104.     /*
  5105.      * Now find which file descriptor is free within the byte.
  5106.      */
  5107.     for (j = 0, bitmaskPtr = bitmasks; 
  5108.      j < 8 && (*bitmapPtr & *bitmaskPtr) != 0; 
  5109.      j++, bitmaskPtr++) {
  5110.     }
  5111.     relocPtr->newFdNum = i * 8 + j;
  5112.     *bitmapPtr |= *bitmaskPtr;
  5113. @
  5114.  
  5115.  
  5116. 1.20
  5117. log
  5118. @Fixed so it returns consistent error codes that can be
  5119. checked by the diskcmds script.
  5120. @
  5121. text
  5122. @d11 1
  5123. a11 1
  5124. static char rcsid[] = "$Header: checkFS.c,v 1.1 88/05/11 17:37:08 brent Exp $ SPRITE (Berkeley)";
  5125. d914 1
  5126. d916 1
  5127. a916 5
  5128.     return;
  5129.     }
  5130.     lastBlock = fdPtr->lastByte / FS_BLOCK_SIZE;
  5131.     if (lastBlock < FS_NUM_DIRECT_BLOCKS) {
  5132.     lastFrag = (fdPtr->lastByte & FS_BLOCK_OFFSET_MASK) / FS_FRAGMENT_SIZE;
  5133. d918 6
  5134. a923 1
  5135.     lastFrag = FS_FRAGMENTS_PER_BLOCK - 1;
  5136. a924 1
  5137.     lastRealBlock = -1;
  5138. d929 10
  5139. a938 2
  5140.     for (i = 0; i < FS_NUM_DIRECT_BLOCKS && i <= lastBlock; i++) {
  5141.     if (fdPtr->direct[i] != FS_NIL_INDEX) {
  5142. d1102 1
  5143. a1102 2
  5144.     fdPtr->lastByte = 
  5145.                 (lastRealBlock + 1) * FS_BLOCK_SIZE - 1;
  5146. d1119 22
  5147. @
  5148.  
  5149.  
  5150. 1.19
  5151. log
  5152. @Set error status flag on error.
  5153. @
  5154. text
  5155. @d11 1
  5156. a11 1
  5157. static char rcsid[] = "$Header: checkFS.c,v 1.18 87/10/21 10:37:47 nelson Exp $ SPRITE (Berkeley)";
  5158. d17 1
  5159. a17 1
  5160. #include "fsDisk.h"
  5161. d48 1
  5162. d51 4
  5163. a54 2
  5164.     {OPT_TRUE, 'c', (Address)&clearDomainNumber,
  5165.     "Clear the domain number field stored in the summary sector"},
  5166. d59 2
  5167. a60 8
  5168.     {OPT_TRUE, 'r', (Address)&recoveryCheck,
  5169.      "The domain wasn't synced => increment all version numbers for recovery."},
  5170.     {OPT_STRING, 'D', (Address)&deviceName,
  5171.     "Required: Name of device, eg \"rsd0\" or \"rxy1\""},
  5172.     {OPT_TRUE, 'H', (Address)&patchHeader,
  5173.     "Update the host ID in the disk header"},
  5174.     {OPT_STRING, 'P', (Address)&partName,
  5175.     "Required: Partition ID: (a, b, c, d, e, f, g)"},
  5176. d65 8
  5177. a72 2
  5178.     {OPT_TRUE, 'W', (Address)&writeDisk,
  5179.     "Write disk (FALSE)"},
  5180. d97 3
  5181. a99 1
  5182.  *    None.
  5183. d123 1
  5184. a123 1
  5185.     Proc_Exit(FAILURE);
  5186. d127 1
  5187. a127 1
  5188.     Proc_Exit(FAILURE);
  5189. d144 1
  5190. a144 1
  5191.     Proc_Exit(status);
  5192. d153 1
  5193. a153 1
  5194.     Proc_Exit(status);
  5195. d160 1
  5196. a160 1
  5197.     Proc_Exit(FAILURE);
  5198. d167 1
  5199. a167 1
  5200.     Proc_Exit(-1);
  5201. d169 1
  5202. a169 1
  5203.     Proc_Exit(0);
  5204. d256 1
  5205. a256 1
  5206.     Proc_Exit(status);
  5207. d347 1
  5208. a347 1
  5209.         Proc_Exit(status);
  5210. d404 1
  5211. a404 1
  5212.         Proc_Exit(status);
  5213. d515 1
  5214. a515 1
  5215.     Proc_Exit(status);
  5216. d547 1
  5217. a547 1
  5218.     Proc_Exit(status);
  5219. d583 1
  5220. a583 1
  5221.     Proc_Exit(status);
  5222. d616 1
  5223. a616 1
  5224.     Proc_Exit(status);
  5225. d650 1
  5226. a650 1
  5227.     Proc_Exit(status);
  5228. d683 1
  5229. a683 1
  5230.     Proc_Exit(status);
  5231. d722 1
  5232. a722 1
  5233.         Proc_Exit(status);
  5234. d729 1
  5235. a729 1
  5236.         Proc_Exit(status);
  5237. d765 1
  5238. a765 1
  5239.     Proc_Exit(status);
  5240. d778 1
  5241. a778 1
  5242.     Proc_Exit(status);
  5243. d811 1
  5244. a811 1
  5245.     Proc_Exit(status);
  5246. d1040 1
  5247. a1040 1
  5248.         Proc_Exit(status);
  5249. d1077 1
  5250. a1077 1
  5251.             Proc_Exit(status);
  5252. d1173 8
  5253. d1182 1
  5254. d1187 1
  5255. a1191 7
  5256.     status = BlockRead(partFID, domainPtr, 
  5257.                *blockNumPtr / FS_FRAGMENTS_PER_BLOCK, 1, 
  5258.                (Address) indirectBlock);
  5259.     if (status != SUCCESS) {
  5260.     Stat_PrintMsg(status, "ProcessIndirectBlock: Read failed");
  5261.     Proc_Exit(status);
  5262.     }
  5263. d1227 1
  5264. a1227 1
  5265.         Proc_Exit(status);
  5266. @
  5267.  
  5268.  
  5269. 1.18
  5270. log
  5271. @Added ability to handle the bad block file.
  5272. @
  5273. text
  5274. @d11 1
  5275. a11 1
  5276. static char rcsid[] = "$Header: checkFS.c,v 1.17 87/10/15 15:16:16 nelson Exp $ SPRITE (Berkeley)";
  5277. d26 1
  5278. d161 5
  5279. d424 1
  5280. d428 1
  5281. d855 1
  5282. d859 1
  5283. d941 1
  5284. d1021 1
  5285. d1095 1
  5286. d1104 1
  5287. d1160 1
  5288. d1196 1
  5289. d1263 1
  5290. d1271 1
  5291. d1287 1
  5292. @
  5293.  
  5294.  
  5295. 1.17
  5296. log
  5297. @Don't increment version on devices for recovery.
  5298. @
  5299. text
  5300. @d11 1
  5301. a11 1
  5302. static char rcsid[] = "$Header: checkFS.c,v 1.16 87/10/12 17:49:03 nelson Exp $ SPRITE (Berkeley)";
  5303. d46 1
  5304. d69 2
  5305. d352 22
  5306. a374 5
  5307.         tDescInfoPtr->origLinkCount = fdPtr->numLinks;
  5308.  
  5309.         modified = FALSE;
  5310.         CheckBlocks(partFID, domainPtr, fdNum, fdPtr,
  5311.                  cylBitmapPtr, newCylBitmapPtr, &modified);
  5312. @
  5313.  
  5314.  
  5315. 1.16
  5316. log
  5317. @Added recovery when detect that disk is not safely taken off line.
  5318. @
  5319. text
  5320. @d11 1
  5321. a11 1
  5322. static char rcsid[] = "$Header: checkFS.c,v 1.15 87/09/30 10:48:45 nelson Exp $ SPRITE (Berkeley)";
  5323. d345 1
  5324. a345 1
  5325.         if (incVersionNumbers) {
  5326. @
  5327.  
  5328.  
  5329. 1.15
  5330. log
  5331. @Changed to understand that Kbytes free is really kbytes and not bytes.
  5332. @
  5333. text
  5334. @d11 1
  5335. a11 1
  5336. static char rcsid[] = "$Header: checkFS.c,v 1.14 87/08/10 10:48:03 nelson Exp $ SPRITE (Berkeley)";
  5337. d44 2
  5338. d48 8
  5339. d58 2
  5340. a61 4
  5341.     {OPT_STRING, 'd', (Address)&devDirectory,
  5342.     "Name of device directory (\"/dev/\")"},
  5343.     {OPT_STRING, 'p', (Address)&firstPartName,
  5344.     "Name of initial partition (\"a\")"},
  5345. d64 2
  5346. a67 4
  5347.     {OPT_TRUE, 'H', (Address)&patchHeader,
  5348.     "Update the host ID in the disk header"},
  5349.     {OPT_TRUE, 'V', (Address)&verbose,
  5350.     "Output information about differences in bitmaps (FALSE)"},
  5351. d74 3
  5352. a76 1
  5353. void CheckFilesystem();
  5354. d280 1
  5355. a280 2
  5356.      * Read in the file descriptor bit map, the cylinder bit map and the
  5357.      * file descriptors.
  5358. d300 13
  5359. d345 3
  5360. d367 9
  5361. d390 1
  5362. a390 1
  5363.                  i < domainPtr->dataCylinders; 
  5364. d738 4
  5365. d748 34
  5366. @
  5367.  
  5368.  
  5369. 1.14
  5370. log
  5371. @Changed to use new method that requires much less memory.
  5372. @
  5373. text
  5374. @d11 1
  5375. a11 1
  5376. static char rcsid[] = "$Header: checkFS.c,v 1.13 87/07/14 14:37:17 nelson Exp $ SPRITE (Berkeley)";
  5377. d686 1
  5378. a686 1
  5379. WriteSummaryInfo(partFID, diskInfoPtr, domainPtr, numFreeKblocks, numFiles)
  5380. d690 1
  5381. a690 1
  5382.     int        numFreeKblocks;    /* Number of 1 Kbyte blocks. */
  5383. d705 1
  5384. a705 1
  5385.     (domainPtr->dataBlocks * 4 - numFreeKblocks) * FS_FRAGMENT_SIZE;   
  5386. @
  5387.  
  5388.  
  5389. 1.13
  5390. log
  5391. @Allow lost and found to be anywhere, not just fd 3.  This allows a corrupted
  5392. lost and found directory to be easily recreated.
  5393. @
  5394. text
  5395. @d11 1
  5396. a11 1
  5397. static char rcsid[] = "$Header: checkFS.c,v 1.12 87/07/14 11:32:12 brent Exp $ SPRITE (Berkeley)";
  5398. d68 1
  5399. a68 1
  5400. ReturnStatus CheckFilesystem();
  5401. d100 1
  5402. d106 1
  5403. a106 1
  5404.     status = FAILURE;
  5405. d110 1
  5406. a110 1
  5407.     status = FAILURE;
  5408. a111 3
  5409.     if (status != SUCCESS) {
  5410.     Proc_Exit(status);
  5411.     }
  5412. d126 1
  5413. a126 2
  5414.     Io_PrintStream(io_StdErr, "Can't open first partition \"%s\" <%x>\n",
  5415.                   firstPartitionName, status);
  5416. d129 5
  5417. a133 1
  5418.     status = Fs_Open(partitionName, FS_READ|FS_WRITE, 0, &partFID);
  5419. d135 1
  5420. a135 2
  5421.     Io_PrintStream(io_StdErr,"Can't open partition to dump \"%s\" <%x>\n",
  5422.                   partitionName, status);
  5423. d142 1
  5424. a142 1
  5425.            "Can't determine partition index from the partition name\n");
  5426. d145 1
  5427. a145 1
  5428.     status = CheckFilesystem(firstPartFID, partFID, partition);
  5429. a146 2
  5430.     Io_Flush(io_StdErr);
  5431.     Io_Flush(io_StdOut);
  5432. a148 1
  5433.     Proc_Exit(status);
  5434. d161 3
  5435. d167 5
  5436. d173 1
  5437. a173 1
  5438. ReturnStatus    CheckBlocks();
  5439. d178 2
  5440. d206 1
  5441. a206 1
  5442. ReturnStatus
  5443. d212 4
  5444. a215 3
  5445.     ReturnStatus        status;
  5446.     BasicDiskInfo       *diskInfoPtr;
  5447.     register    FdInfo      *descInfoPtr;
  5448. d217 8
  5449. a224 3
  5450.     unsigned    char      *fdBitmapPtr;
  5451.     unsigned    char      *cylBitmapPtr;
  5452.     unsigned    char      *newCylBitmapPtr;
  5453. d232 3
  5454. a234 1
  5455.     return(FAILURE);
  5456. d241 2
  5457. a242 6
  5458.     status = ReadDomainHeader(partFID, diskInfoPtr, domainPtr);
  5459.     if (status != SUCCESS) {
  5460.     Io_PrintStream(io_StdErr, "DomainHeader read failed <%x>\n", status);
  5461.     Io_Flush(io_StdErr);
  5462.     return(status);
  5463.     }
  5464. a275 5
  5465.     if (fdBitmapPtr == (unsigned char *) NULL) {
  5466.     Io_PrintStream(io_StdErr, "File desc bitmap read failed.\n");
  5467.     Io_Flush(io_StdErr);
  5468.     return(FAILURE);
  5469.     }
  5470. a276 5
  5471.     if (cylBitmapPtr == (unsigned char *) NULL) {
  5472.     Io_PrintStream(io_StdErr, "Cylinder bitmap read failed.\n");
  5473.     Io_Flush(io_StdErr);
  5474.     return(FAILURE);
  5475.     }
  5476. a280 7
  5477.     descInfoPtr = ReadFileDesc(partFID, domainPtr);
  5478.     if (descInfoPtr == (FdInfo *) NULL) {
  5479.     Io_PrintStream(io_StdErr, "File descriptor read failed.\n");
  5480.     Io_Flush(io_StdErr);
  5481.     return(FAILURE);
  5482.     }
  5483.     
  5484. d282 1
  5485. a282 1
  5486.      * Recreate the file descriptor bit map.
  5487. d284 2
  5488. a285 3
  5489.     if (!silent) {
  5490.     Io_PrintStream(io_StdErr, "Checking file descriptor bitmap:\n");
  5491.     }
  5492. a286 6
  5493.     CheckFDBitmap(fdBitmapPtr, descInfoPtr, domainPtr);
  5494.  
  5495.     /*
  5496.      * Check the block counts and make sure that all blocks are
  5497.      * referenced.  Also recreate the data block bitmap.
  5498.      */
  5499. d290 1
  5500. d292 5
  5501. d298 1
  5502. a298 1
  5503.     Io_PrintStream(io_StdErr, "\nChecking file blocks:\n");
  5504. d301 43
  5505. a343 7
  5506.     status = CheckBlocks(cylBitmapPtr, newCylBitmapPtr, descInfoPtr, 
  5507.              partFID, domainPtr);
  5508.     if (status != SUCCESS) {
  5509.     Io_PrintStream(io_StdErr, "Indirect block read failed with status %x\n",
  5510.             status);
  5511.     Io_Flush(io_StdErr);
  5512.     return(status);
  5513. d345 1
  5514. a345 1
  5515.     
  5516. d347 30
  5517. d384 1
  5518. a384 8
  5519.     status = CheckDirTree(partFID, domainPtr, descInfoPtr);
  5520.     if (status != SUCCESS) {
  5521.     Io_PrintStream(io_StdErr, 
  5522.                "Checking directory tree returned status %x\n",
  5523.                status);
  5524.     Io_Flush(io_StdErr);
  5525.     return(status);
  5526.     }
  5527. d395 1
  5528. a395 1
  5529.     return(SUCCESS);
  5530. d411 8
  5531. a418 19
  5532.     status = WriteFileDescBitmap(partFID, domainPtr, fdBitmapPtr);
  5533.     if (status != SUCCESS) {
  5534.     Io_PrintStream(io_StdErr, "File desc bitmap write failed.\n");
  5535.     Io_Flush(io_StdErr);
  5536.     return(status);
  5537.     }
  5538.     status = WriteBitmap(partFID, domainPtr, newCylBitmapPtr);
  5539.     if (status != SUCCESS) {
  5540.     Io_PrintStream(io_StdErr, "Cylinder bitmap write failed.\n");
  5541.     Io_Flush(io_StdErr);
  5542.     return(status);
  5543.     }
  5544.     status = WriteFileDesc(partFID, domainPtr, descInfoPtr);
  5545.     if (status != SUCCESS) {
  5546.     Io_PrintStream(io_StdErr, "File descriptor write failed.\n");
  5547.     Io_Flush(io_StdErr);
  5548.     return(status);
  5549.     }
  5550.     status = WriteSummaryInfo(partFID, diskInfoPtr, domainPtr, 
  5551. a419 7
  5552.     if (status != SUCCESS) {
  5553.     Io_PrintStream(io_StdErr, "Summary info write failed.\n");
  5554.     Io_Flush(io_StdErr);
  5555.     return(status);
  5556.     }
  5557.  
  5558.     return(SUCCESS);
  5559. d431 1
  5560. a431 1
  5561.  *    A return code from the read.
  5562. d438 1
  5563. a438 2
  5564.  
  5565. ReturnStatus
  5566. d448 4
  5567. a451 1
  5568.     return(status);
  5569. d463 1
  5570. a463 1
  5571.  *    A return code from the read.
  5572. d470 1
  5573. a470 2
  5574.  
  5575. ReturnStatus
  5576. d480 4
  5577. a483 1
  5578.     return(status);
  5579. d490 1
  5580. a490 1
  5581.  * ReadFileDescBitmap --
  5582. d517 2
  5583. a518 3
  5584.     return((unsigned char *) NULL);
  5585.     } else {
  5586.     return(bitmap);
  5587. d520 1
  5588. d532 1
  5589. a532 1
  5590.  *    A return status.
  5591. d539 1
  5592. a539 1
  5593. ReturnStatus
  5594. d545 8
  5595. a552 2
  5596.     return(BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  5597.               domainPtr->fdBitmapBlocks, (Address)bitmap));
  5598. d584 2
  5599. a585 3
  5600.     return((unsigned char *) NULL);
  5601.     } else {
  5602.     return(bitmap);
  5603. d587 1
  5604. d606 1
  5605. a606 1
  5606. ReturnStatus
  5607. d612 1
  5608. a612 3
  5609.     return(BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  5610.               domainPtr->bitmapBlocks, (Address) bitmap));
  5611. }
  5612. d614 5
  5613. a618 54
  5614.  
  5615. /*
  5616.  *----------------------------------------------------------------------
  5617.  *
  5618.  * ReadFileDesc --
  5619.  *
  5620.  *    Read the file descriptors off of disk.
  5621.  *
  5622.  * Results:
  5623.  *    A pointer to an array of file descriptor info structs.
  5624.  *
  5625.  * Side effects:
  5626.  *    None.
  5627.  *
  5628.  *----------------------------------------------------------------------
  5629.  */
  5630.  
  5631. FdInfo *
  5632. ReadFileDesc(partFID, domainPtr)
  5633.     int partFID;
  5634.     register FsDomainHeader *domainPtr;
  5635. {
  5636.     ReturnStatus     status;
  5637.     FdInfo        *retPtr;
  5638.     char         block[FS_BLOCK_SIZE];
  5639.     register    FdInfo    *fdInfoPtr;
  5640.     register     int     i;
  5641.     register     int     j;
  5642.     int             fdsRead;
  5643.  
  5644.     fdInfoPtr = (FdInfo *) Mem_Alloc(domainPtr->numFileDesc * sizeof(FdInfo));
  5645.     retPtr = fdInfoPtr;
  5646.  
  5647.     fdsRead = 0;
  5648.     for (i = 0; 
  5649.      i < (domainPtr->numFileDesc + FS_FILE_DESC_PER_BLOCK - 1) / 
  5650.         FS_FILE_DESC_PER_BLOCK;
  5651.      i++) {
  5652.     status = BlockRead(partFID, domainPtr, domainPtr->fileDescOffset + i,
  5653.                 1, (Address) block);
  5654.     if (status != SUCCESS) {
  5655.         return((FdInfo *) NULL);
  5656.     }
  5657.     for (j = 0; 
  5658.          j < FS_FILE_DESC_PER_BLOCK && fdsRead < domainPtr->numFileDesc;
  5659.          j++, fdsRead++, fdInfoPtr++) {
  5660.          Byte_Copy(sizeof(FsFileDescriptor), 
  5661.                (Address) &block[j * FS_MAX_FILE_DESC_SIZE],
  5662.                (Address) &fdInfoPtr->fileDesc);
  5663.          fdInfoPtr->linkCount = 0;
  5664.          fdInfoPtr->parentLinkCount = 0;
  5665.          fdInfoPtr->blockCount = 0;
  5666.          fdInfoPtr->seen = FALSE;
  5667.     }
  5668. a619 2
  5669.  
  5670.     return(retPtr);
  5671. d631 1
  5672. a631 1
  5673.  *    A pointer to an array of file descriptor info structs.
  5674. d634 1
  5675. a634 1
  5676.  *    None.
  5677. d638 2
  5678. a639 3
  5679.  
  5680. ReturnStatus
  5681. WriteFileDesc(partFID, domainPtr, fdInfoPtr)
  5682. a641 1
  5683.     register    FdInfo        *fdInfoPtr;
  5684. d644 4
  5685. a647 4
  5686.     char         block[FS_BLOCK_SIZE];
  5687.     register     int     i;
  5688.     register     int     j;
  5689.     int             fdsWritten;
  5690. d649 9
  5691. a657 11
  5692.     fdsWritten = 0;
  5693.     for (i = 0; 
  5694.      i < (domainPtr->numFileDesc + FS_FILE_DESC_PER_BLOCK - 1) / 
  5695.         FS_FILE_DESC_PER_BLOCK;
  5696.      i++) {
  5697.     for (j = 0; 
  5698.          j < FS_FILE_DESC_PER_BLOCK && fdsWritten < domainPtr->numFileDesc;
  5699.          j++, fdsWritten++, fdInfoPtr++) {
  5700.          Byte_Copy(sizeof(FsFileDescriptor), 
  5701.                (Address) &fdInfoPtr->fileDesc,
  5702.                (Address) &block[j * FS_MAX_FILE_DESC_SIZE]);
  5703. d659 3
  5704. a661 2
  5705.     status = BlockWrite(partFID, domainPtr, domainPtr->fileDescOffset + i,
  5706.                 1, (Address) block);
  5707. d663 2
  5708. a664 1
  5709.         return(status);
  5710. a666 2
  5711.  
  5712.     return(SUCCESS);
  5713. d678 1
  5714. a678 1
  5715.  *    A return code from the read or write.
  5716. d685 1
  5717. a685 1
  5718. ReturnStatus
  5719. d699 2
  5720. a700 1
  5721.     return(status);
  5722. d708 2
  5723. a709 1
  5724.     return(status);
  5725. d734 5
  5726. a738 4
  5727. CheckFDBitmap(bitmapPtr, fdInfoPtr, domainPtr)
  5728.     register    unsigned char     *bitmapPtr;
  5729.     register    FdInfo        *fdInfoPtr;
  5730.     register    FsDomainHeader    *domainPtr;
  5731. d740 4
  5732. a743 3
  5733.     int    i, j, fd;
  5734.     register unsigned char *bitmaskPtr;
  5735.     Boolean           allocated;
  5736. d745 4
  5737. a748 3
  5738.     for (fd = 0, i = 0; 
  5739.      i < (domainPtr->numFileDesc + BITS_PER_BYTE - 1) / BITS_PER_BYTE; 
  5740.      i++, bitmapPtr++){
  5741. d750 11
  5742. a760 9
  5743.          j < BITS_PER_BYTE && fd < domainPtr->numFileDesc; 
  5744.          j++, fd++, bitmaskPtr++) {
  5745.         allocated = *bitmapPtr & *bitmaskPtr;
  5746.         if (allocated && (fdInfoPtr->fileDesc.flags & FS_FD_FREE)) {
  5747.         Io_PrintStream(io_StdErr, "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n", fd);
  5748.         *bitmapPtr &= ~*bitmaskPtr;
  5749.         } else if (!allocated && !(fdInfoPtr->fileDesc.flags& FS_FD_FREE)) {
  5750.         Io_PrintStream(io_StdErr, "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n", fd);
  5751.         *bitmapPtr |= *bitmaskPtr;
  5752. a761 1
  5753.         fdInfoPtr++;
  5754. a763 1
  5755.     Io_Flush(io_StdErr);
  5756. d782 7
  5757. a788 3
  5758.  
  5759. ReturnStatus
  5760. CheckBlocks(cylBitmapPtr, newCylBitmapPtr, descInfoPtr, partFID, domainPtr)
  5761. d791 1
  5762. a791 3
  5763.     register FdInfo    *descInfoPtr;
  5764.     int         partFID;
  5765.     FsDomainHeader    *domainPtr;
  5766. a793 2
  5767.     register unsigned char     *oldPtr;
  5768.     register unsigned char     *newPtr;
  5769. a794 1
  5770.     int                fd;
  5771. a800 1
  5772.     int                blockNum;
  5773. d803 1
  5774. d805 14
  5775. a818 16
  5776.     for (fd = 0; fd < domainPtr->numFileDesc; fd++, descInfoPtr++) {
  5777.     if (!(descInfoPtr->fileDesc.flags & FS_FD_ALLOC)) {
  5778.         continue;
  5779.     }
  5780.     numFiles++;
  5781.     if (descInfoPtr->fileDesc.lastByte == -1) {
  5782.         continue;
  5783.     }
  5784.     lastBlock = descInfoPtr->fileDesc.lastByte / FS_BLOCK_SIZE;
  5785.     if (lastBlock < FS_NUM_DIRECT_BLOCKS) {
  5786.         lastFrag = (descInfoPtr->fileDesc.lastByte & FS_BLOCK_OFFSET_MASK) /
  5787.                 FS_FRAGMENT_SIZE;
  5788.     } else {
  5789.         lastFrag = FS_FRAGMENTS_PER_BLOCK - 1;
  5790.     }
  5791.     lastRealBlock = -1;
  5792. d820 12
  5793. a831 15
  5794.     /*
  5795.      * First check direct blocks.
  5796.      */
  5797.     for (i = 0; i < FS_NUM_DIRECT_BLOCKS && i <= lastBlock; i++) {
  5798.         if (descInfoPtr->fileDesc.direct[i] != FS_NIL_INDEX) {
  5799.         if (i == lastBlock) {
  5800.             status = MarkBitmap(fd, descInfoPtr->fileDesc.direct[i],
  5801.                         newCylBitmapPtr,
  5802.                             lastFrag + 1, domainPtr);
  5803.             if (status == SUCCESS) {
  5804.             if (lastFrag + 1 != FS_FRAGMENTS_PER_BLOCK) {
  5805.                 numFrags++;
  5806.             }
  5807.             descInfoPtr->blockCount += lastFrag + 1;
  5808.             numBlocks += lastFrag + 1;
  5809. d833 9
  5810. d843 6
  5811. a848 13
  5812.             if (descInfoPtr->fileDesc.direct[i] & 
  5813.             (FS_FRAGMENTS_PER_BLOCK - 1)) {
  5814.             Io_PrintStream(io_StdErr, "Fragmented block that is not the last in file %d. Block deleted.\n",
  5815.                     fd);
  5816.             status = FAILURE;
  5817.             } else {
  5818.             status = MarkBitmap(fd, descInfoPtr->fileDesc.direct[i],
  5819.                         newCylBitmapPtr,
  5820.                         FS_FRAGMENTS_PER_BLOCK, domainPtr);
  5821.             if (status == SUCCESS) {
  5822.                 descInfoPtr->blockCount += FS_FRAGMENTS_PER_BLOCK;
  5823.                 numBlocks += FS_FRAGMENTS_PER_BLOCK;
  5824.             }
  5825. a850 8
  5826.         if (status != SUCCESS) {
  5827.             descInfoPtr->fileDesc.direct[i] = FS_NIL_INDEX;
  5828.         } else {
  5829.             lastRealBlock = i;
  5830.         }
  5831.         } else if (descInfoPtr->fileDesc.fileType == FS_DIRECTORY) {
  5832.         Io_PrintStream(io_StdErr, "Hole in directory %d.\n", fd);
  5833.         goto truncFile;
  5834. d852 3
  5835. a854 6
  5836.     }
  5837.     if (i > lastBlock) {
  5838.         if (lastRealBlock != lastBlock) {
  5839.         Io_PrintStream(io_StdErr, "Missing last block in file %d.\n",
  5840.                    fd);
  5841.         goto truncFile;
  5842. d856 1
  5843. a856 1
  5844.         goto checkBlockCount;
  5845. d858 3
  5846. d862 10
  5847. d873 72
  5848. a944 8
  5849.     /*
  5850.      * Now check the singly indirect block.
  5851.      */
  5852.     if (descInfoPtr->fileDesc.indirect[0] == FS_NIL_INDEX) {
  5853.         if (descInfoPtr->fileDesc.fileType == FS_DIRECTORY) {
  5854.         Io_PrintStream(io_StdErr, "Hole in directory %d because single indirect block is NIL.\n",
  5855.                 fd);
  5856.         goto truncFile;
  5857. a945 2
  5858.         i += FS_INDICES_PER_BLOCK;
  5859.     } else {
  5860. d947 5
  5861. a951 5
  5862.         status = ProcessIndirectBlock(fd, descInfoPtr, 
  5863.                       &descInfoPtr->fileDesc.indirect[0],
  5864.                               newCylBitmapPtr, partFID, domainPtr, 
  5865.                       lastBlock, &tBlock, &dirty, 
  5866.                       &lastRealBlock);
  5867. d954 2
  5868. a955 2
  5869.         Io_PrintStream(io_StdErr, "Hole in directory %d in single indirect block\n",
  5870.                 fd);
  5871. d958 2
  5872. a959 1
  5873.         return(status);
  5874. d963 8
  5875. a970 43
  5876.     if (i > lastBlock) {
  5877.         if (lastRealBlock != lastBlock) {
  5878.         Io_PrintStream(io_StdErr, "Missing last block in singly indirect block for file %d\n",
  5879.                 fd);
  5880.         goto truncFile;
  5881.         } else {
  5882.         goto checkBlockCount;
  5883.         }
  5884.     } else if (descInfoPtr->fileDesc.indirect[1] == FS_NIL_INDEX) {
  5885.         Io_PrintStream(io_StdErr, "Last block missing in file %d because doubly indirect block is nil\n", fd);
  5886.         goto truncFile;
  5887.     }
  5888.  
  5889.     /*
  5890.      * Now check doubly indirect blocks.
  5891.      */
  5892.     indBlock = descInfoPtr->fileDesc.indirect[1];
  5893.     if (indBlock & (FS_FRAGMENTS_PER_BLOCK - 1)) {
  5894.         Io_PrintStream(io_StdErr, "Doubly indirect block on non-block boundary for file %d.  Block deleted.\n", fd);
  5895.         status = FAILURE;
  5896.     } else {
  5897.         status = MarkBitmap(fd, 
  5898.             indBlock - domainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK, 
  5899.             newCylBitmapPtr,
  5900.             FS_FRAGMENTS_PER_BLOCK, domainPtr);
  5901.     }
  5902.     if (status == SUCCESS) {
  5903.         status = BlockRead(partFID, domainPtr, 
  5904.                    indBlock / FS_FRAGMENTS_PER_BLOCK,
  5905.                    1, (Address) dblIndirectBlock);
  5906.         if (status != SUCCESS) {
  5907.         return(status);
  5908.         }
  5909.         for (j = 0, indexPtr = (int *) dblIndirectBlock; 
  5910.          j < FS_INDICES_PER_BLOCK && i <= lastBlock; 
  5911.          j++, indexPtr++) {
  5912.         if (*indexPtr == FS_NIL_INDEX) {
  5913.             if (descInfoPtr->fileDesc.fileType == FS_DIRECTORY) {
  5914.             Io_PrintStream(io_StdErr, "Hole in directory %d in doubly indirect block\n",
  5915.                 fd);
  5916.             goto truncFile;
  5917.             }
  5918.             continue;
  5919. a971 14
  5920.         tBlock = i;
  5921.         status = ProcessIndirectBlock(fd, descInfoPtr, indexPtr, 
  5922.                           newCylBitmapPtr, 
  5923.                           partFID, domainPtr, lastBlock, 
  5924.                           &tBlock, &dirty, &lastRealBlock);
  5925.         i = tBlock;
  5926.         if (status == DIR_HOLE) {
  5927.             Io_PrintStream(io_StdErr, "Hole in directory %d in doubly indirect blocks (2)\n",
  5928.                    fd);
  5929.             goto truncFile;
  5930.         } else if (status != SUCCESS) {
  5931.             return(status);
  5932.         }
  5933.         numBlocks += FS_FRAGMENTS_PER_BLOCK;
  5934. a972 14
  5935.         if (dirty) {
  5936.         if (writeDisk) {
  5937.             status = BlockWrite(partFID, domainPtr, 
  5938.                    indBlock / FS_FRAGMENTS_PER_BLOCK,
  5939.                    1, (Address) dblIndirectBlock);
  5940.             if (status != SUCCESS) {
  5941.             Io_PrintStream(io_StdErr, "Could not write back indirect block\n");
  5942.             Io_Flush(io_StdErr);
  5943.             return(status);
  5944.             }
  5945.         }
  5946.         }
  5947.     } else {
  5948.         descInfoPtr->fileDesc.indirect[1] = FS_NIL_INDEX;
  5949. d974 4
  5950. d979 3
  5951. a981 3
  5952.     if (lastRealBlock == lastBlock) {
  5953.         goto checkBlockCount;
  5954.     }
  5955. d985 9
  5956. a993 8
  5957.     if (lastRealBlock != -1) {
  5958.         descInfoPtr->fileDesc.lastByte = 
  5959.                 (lastRealBlock + 1) * FS_BLOCK_SIZE - 1;
  5960.     } else {
  5961.         descInfoPtr->fileDesc.lastByte = -1;
  5962.     }
  5963.     Io_PrintStream(io_StdErr,"Truncating file %d to length %d\n", fd,
  5964.                  descInfoPtr->fileDesc.lastByte + 1);
  5965. d997 5
  5966. a1001 5
  5967.     if (descInfoPtr->blockCount != descInfoPtr->fileDesc.numKbytes) {
  5968.         Io_PrintStream(io_StdErr, "Block count corrected for file %d.  Is %d should be %d.\n", 
  5969.         fd, descInfoPtr->fileDesc.numKbytes, descInfoPtr->blockCount);
  5970.         descInfoPtr->fileDesc.numKbytes = descInfoPtr->blockCount;
  5971.     }
  5972. a1002 30
  5973.  
  5974.     Io_Flush(io_StdErr);
  5975.  
  5976.  
  5977.     /*
  5978.      * Now compare the two bitmaps.
  5979.      */
  5980.     if (verbose) {
  5981.     Io_PrintStream(io_StdErr,
  5982.             "\nComparing old and new data block bit maps\n");
  5983.     for (oldPtr = cylBitmapPtr, newPtr = newCylBitmapPtr, 
  5984.                                 i = 0, blockNum = 0; 
  5985.                  i < domainPtr->dataCylinders; 
  5986.         i++, oldPtr = &cylBitmapPtr[bytesPerCylinder * i], 
  5987.              newPtr = &newCylBitmapPtr[bytesPerCylinder * i]) {
  5988.         for (j = 0; 
  5989.              j < bytesPerCylinder; 
  5990.          j++, oldPtr++, newPtr++, blockNum += 2) {
  5991.              if ((*oldPtr & 0xf0) != (*newPtr & 0xf0)) {
  5992.              Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", blockNum * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0xf0, *newPtr & 0xf0);
  5993.              } 
  5994.              if ((*oldPtr & 0x0f) != (*newPtr & 0x0f)) {
  5995.              Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", (blockNum + 1) * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0x0f, *newPtr & 0x0f);
  5996.              }
  5997.         }
  5998.         }
  5999.  
  6000.         Io_Flush(io_StdErr);
  6001.     }
  6002.     return(SUCCESS);
  6003. d1024 1
  6004. a1024 1
  6005. ProcessIndirectBlock(fdNum, descInfoPtr, blockNumPtr, newCylBitmapPtr, partFID,
  6006. d1026 1
  6007. a1026 1
  6008.             lastRealBlockPtr)
  6009. d1029 1
  6010. a1029 1
  6011.     register FdInfo    *descInfoPtr;      /* Actual file descriptor. */
  6012. d1043 4
  6013. d1067 1
  6014. d1076 2
  6015. a1077 3
  6016.     Io_PrintStream(io_StdErr, "Could not read indirect block\n");
  6017.     Io_Flush(io_StdErr);
  6018.     return(status);
  6019. d1083 1
  6020. a1083 1
  6021.         if (descInfoPtr->fileDesc.fileType == FS_DIRECTORY) {
  6022. d1098 1
  6023. a1098 1
  6024.         descInfoPtr->blockCount += FS_FRAGMENTS_PER_BLOCK;
  6025. d1112 2
  6026. a1113 2
  6027.         Io_PrintStream(io_StdErr, "Error writing out indirect block\n");
  6028.         return(status);
  6029. @
  6030.  
  6031.  
  6032. 1.12
  6033. log
  6034. @Changed to include ioc.h.
  6035. @
  6036. text
  6037. @d11 1
  6038. a11 1
  6039. static char rcsid[] = "$Header: checkFS.c,v 1.11 87/06/03 19:30:40 nelson Exp $ SPRITE (Berkeley)";
  6040. d328 1
  6041. a328 1
  6042.                "Read failed checking directory tree with status %x\n",
  6043. @
  6044.  
  6045.  
  6046. 1.11
  6047. log
  6048. @Added updating of summary info.
  6049. @
  6050. text
  6051. @d11 1
  6052. a11 1
  6053. static char rcsid[] = "$Header: checkFS.c,v 1.10 87/06/01 15:41:47 nelson Exp $ SPRITE (Berkeley)";
  6054. a16 1
  6055. #include "ioc.h"
  6056. @
  6057.  
  6058.  
  6059. 1.10
  6060. log
  6061. @Fixed lint complaints.
  6062. @
  6063. text
  6064. @d11 1
  6065. a11 1
  6066. static char rcsid[] = "$Header: checkFS.c,v 1.9 87/05/30 12:17:27 nelson Exp $ SPRITE (Berkeley)";
  6067. d378 7
  6068. d681 43
  6069. @
  6070.  
  6071.  
  6072. 1.9
  6073. log
  6074. @Now reports number of files, blocks and fragments.
  6075. @
  6076. text
  6077. @d11 1
  6078. a11 1
  6079. static char rcsid[] = "$Header: checkFS.c,v 1.8 87/05/27 10:13:36 nelson Exp $ SPRITE (Berkeley)";
  6080. d20 3
  6081. a527 1
  6082.     int kbytesPerCyl;
  6083. d532 1
  6084. a532 1
  6085.                 domainPtr->bitmapBlocks, bitmap);
  6086. d563 1
  6087. a563 1
  6088.               domainPtr->bitmapBlocks, bitmap));
  6089. d605 1
  6090. a605 1
  6091.                 1, block);
  6092. d667 1
  6093. a667 1
  6094.                 1, block);
  6095. d890 1
  6096. a890 1
  6097.                    1, dblIndirectBlock);
  6098. d924 1
  6099. a924 1
  6100.                    1, dblIndirectBlock);
  6101. d1054 2
  6102. a1055 1
  6103.                *blockNumPtr / FS_FRAGMENTS_PER_BLOCK, 1, indirectBlock);
  6104. d1092 1
  6105. a1092 1
  6106.                 1, indirectBlock);
  6107. @
  6108.  
  6109.  
  6110. 1.8
  6111. log
  6112. @Cleanup.
  6113. @
  6114. text
  6115. @d11 1
  6116. a11 1
  6117. static char rcsid[] = "$Header: checkFS.c,v 1.6 87/04/25 10:24:20 brent Exp $ SPRITE (Berkeley)";
  6118. d21 4
  6119. d332 8
  6120. a721 1
  6121.  
  6122. d764 1
  6123. a764 2
  6124.     if (!(descInfoPtr->fileDesc.flags & FS_FD_ALLOC) ||
  6125.          descInfoPtr->fileDesc.lastByte == -1) {
  6126. d767 4
  6127. d790 3
  6128. d794 1
  6129. d808 1
  6130. d857 1
  6131. d916 1
  6132. d1078 1
  6133. @
  6134.  
  6135.  
  6136. 1.7
  6137. log
  6138. @Fixed bug where wasn't handling disks that had an odd number of blocks
  6139. per cylinder correctly.
  6140. @
  6141. text
  6142. @a153 1
  6143.  
  6144. a169 1
  6145.  
  6146. d253 1
  6147. a257 1
  6148.  
  6149. a283 1
  6150.  
  6151. a293 1
  6152.  
  6153. a314 1
  6154.  
  6155. a768 1
  6156.  
  6157. a815 1
  6158.  
  6159. a854 1
  6160.  
  6161. a942 1
  6162.  
  6163. d944 2
  6164. a945 1
  6165.     Io_PrintStream(io_StdErr, "\nComparing old and new data block bit maps\n");
  6166. @
  6167.  
  6168.  
  6169. 1.6
  6170. log
  6171. @Added a hook to patch the spriteID in the domain header that
  6172. the server needs if reverse arp doesn't find out a sprite ID.
  6173. @
  6174. text
  6175. @d11 1
  6176. a11 1
  6177. static char rcsid[] = "$Header: checkFS.c,v 1.5 87/04/24 17:36:45 douglis Exp $ SPRITE (Berkeley)";
  6178. d1116 2
  6179. d1132 8
  6180. a1139 2
  6181.     bytePtr = GetBitmapPtr(domainPtr, bitmapPtr, blockNum / FS_FRAGMENTS_PER_BLOCK);
  6182.     bitmaskPtr = &bitmasks[blockNum & 0x7];
  6183. @
  6184.  
  6185.  
  6186. 1.5
  6187. log
  6188. @Added silent option mode
  6189. @
  6190. text
  6191. @d11 1
  6192. a11 1
  6193. static char rcsid[] = "$Header: checkFS.c,v 1.4 86/12/16 13:21:42 nelson Exp $ SPRITE (Berkeley)";
  6194. d34 1
  6195. d52 2
  6196. a138 1
  6197.  
  6198. d228 6
  6199. d235 20
  6200. d346 3
  6201. d398 30
  6202. @
  6203.  
  6204.  
  6205. 1.4
  6206. log
  6207. @Fixed various bugs and enhanced error statements.
  6208. @
  6209. text
  6210. @d11 1
  6211. a11 1
  6212. static char rcsid[] = "$Header: checkFS.c,v 1.3 86/11/10 11:33:00 nelson Exp $ SPRITE (Berkeley)";
  6213. d36 1
  6214. d47 2
  6215. d259 3
  6216. a261 1
  6217.     Io_PrintStream(io_StdErr, "Checking file descriptor bitmap:\n");
  6218. d274 3
  6219. a276 1
  6220.     Io_PrintStream(io_StdErr, "\nChecking file blocks:\n");
  6221. d292 3
  6222. a294 1
  6223.     Io_PrintStream(io_StdErr, "\nTraversing directory tree:\n\n");
  6224. d309 3
  6225. a311 1
  6226.     Io_PrintStream(io_StdErr, "Writing disk\n");
  6227. @
  6228.  
  6229.  
  6230. 1.3
  6231. log
  6232. @Changed names so can compile again.
  6233. @
  6234. text
  6235. @d11 1
  6236. a11 1
  6237. static char rcsid[] = "$Header: checkFS.c,v 1.2 86/09/19 18:18:00 nelson Exp $ SPRITE (Berkeley)";
  6238. d35 1
  6239. d48 2
  6240. a196 1
  6241.     register     int        numBlocks;
  6242. d243 2
  6243. a244 1
  6244.     Byte_Zero(domainPtr->bitmapBlocks * FS_BLOCK_SIZE, newCylBitmapPtr);
  6245. a381 1
  6246.     register int index;
  6247. a446 2
  6248.     int bitmapBytesPerCyl;
  6249.     int index;
  6250. d535 1
  6251. d880 1
  6252. d882 15
  6253. a896 12
  6254.     for (oldPtr = cylBitmapPtr, newPtr = newCylBitmapPtr, i = 0, blockNum = 0; 
  6255.      i < domainPtr->dataCylinders; 
  6256.      i++, oldPtr = &cylBitmapPtr[bytesPerCylinder * i], 
  6257.           newPtr = &newCylBitmapPtr[bytesPerCylinder * i]) {
  6258.     for (j = 0; 
  6259.          j < bytesPerCylinder; 
  6260.          j++, oldPtr++, newPtr++, blockNum += 2) {
  6261.         if ((*oldPtr & 0xf0) != (*newPtr & 0xf0)) {
  6262.         Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", blockNum * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0xf0, *newPtr & 0xf0);
  6263.         } 
  6264.         if ((*oldPtr & 0x0f) != (*newPtr & 0x0f)) {
  6265.         Io_PrintStream(io_StdErr, "Block %d: old %x new %x.\n", (blockNum + 1) * FS_FRAGMENTS_PER_BLOCK, *oldPtr & 0x0f, *newPtr & 0x0f);
  6266. d898 2
  6267. a899 1
  6268.     }
  6269. a900 3
  6270.  
  6271.     Io_Flush(io_StdErr);
  6272.  
  6273. @
  6274.  
  6275.  
  6276. 1.2
  6277. log
  6278. @*** empty log message ***
  6279. @
  6280. text
  6281. @d11 1
  6282. a11 1
  6283. static char rcsid[] = "$Header: checkFS.c,v 1.1 86/07/27 12:52:54 nelson Exp $ SPRITE (Berkeley)";
  6284. d214 1
  6285. a214 1
  6286.                          BYTES_PER_SECTOR);
  6287. d253 1
  6288. a253 1
  6289.     Io_PrintStream(io_StdErr, "\nChecking file descriptor bitmap:\n\n");
  6290. d266 1
  6291. a266 1
  6292.     Io_PrintStream(io_StdErr, "\nChecking file blocks:\n\n");
  6293. d631 1
  6294. a631 1
  6295.         Io_PrintStream(io_StdErr, "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n", fd);
  6296. d634 1
  6297. a634 1
  6298.         Io_PrintStream(io_StdErr, "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n", fd);
  6299. @
  6300.  
  6301.  
  6302. 1.1
  6303. log
  6304. @Initial revision
  6305. @
  6306. text
  6307. @d11 1
  6308. a11 1
  6309. static char rcsid[] = "$Header: makeFilesystem.c,v 1.1 86/06/19 17:11:30 brent Exp $ SPRITE (Berkeley)";
  6310. d866 2
  6311. a867 1
  6312.         Io_PrintStream(io_StdErr, "Block count wrong for file %d\n", fd);
  6313. d888 1
  6314. a888 1
  6315.         Io_PrintStream(io_StdErr, "Block %d differs.\n", blockNum * FS_FRAGMENTS_PER_BLOCK);
  6316. d891 1
  6317. a891 1
  6318.         Io_PrintStream(io_StdErr, "Block %d differs.\n", (blockNum + 1) * FS_FRAGMENTS_PER_BLOCK);
  6319. @
  6320.